使用管道将 tar stdout 保存到文件

使用管道将 tar stdout 保存到文件

我尝试使用 SSH 将存档下载到远程计算机,并在远程客户端上提取存档,因为它具有更好的性能。

我有一个非常简单的脚本,用于下载存档,然后tar xjOf通过远程客户端上的 ssh 来提取文件。我现在想将 tar 命令的输出通过管道传输到某个可以将提取的文件保存在本地客户端上的进程。我认为 tar 应该具有这种能力,但我无法找到任何解决方案。

#!/bin/bash
ssh $1@$2 'wget https://url.to.my/archive.tar.bz2' #Save the archive to the remote client
ssh $1@$2 'tar archive.tar.bz2 -xjOf' | ??? #What local tool can be used to take the output and save the files from it? 

我对 Linux 和 shell 脚本相当陌生,因此代码可能有很多改进的方法,但现在我只想知道如何将这些文件保存到本地客户端。

感谢您的帮助

答案1

如果您想在远程计算机上下载并解压缩存档,但在本地计算机上提取文件,您可以这样做:

you@local ssh <remote> "wget -qO - https://url.to.my/archive.tar.bz2 | bunzip2" | tar x

这里发生的事情是这样的:

  1. 您可以在远程计算机上执行引号内的命令。因此下载和解压缩发生在远程计算机上。
  2. 该命令的输出通过管道传输到本地计算机上的 tar 并在本地提取。
  3. 正如 Andre Beaud 和您自己指出的那样,这也意味着未压缩的数据通过 ssh 从远程传输到本地。这导致从更快的远程解压缩获得的时间可能超过远程和本地之间的网络流量损失的时间之间的权衡。
  4. 不过好的一点是解压完成了尽管它是从远程的网址下载的。

这里有几点需要注意:

  1. 您的脚本在这里是一个命令行。该命令使用 ssh 的功能在远程计算机上执行命令马上并将输出返回到本地计算机。
  2. 与往常一样,您必须阅读文档以了解命令是否可以读取(标准输入)和/或写入(标准输出)数据流以及如何指示命令执行此操作。
    • Wget 可以和 -qO 之后的破折号 (-) 指示 wget 写入标准输出 (stout)。
    • Bunzip 也可以,如果没有给出文件,则从 stin 获取输入并写入 stout。
    • 默认情况下,Tar 也从 stin 获取输入。
  3. 文件格式还需要支持流数据。 tar 和 bzip2 格式都可以,但并非每种格式都可以。 (例如拉链)
  4. 在这种情况下,wget 获得两个参数。第一个 -q 选项(安静)被添加到 wget 中以关闭日志和错误信息的输出,因此它不是 tar 读取的数据流的一部分。第二个 -O 类似于 shell 重定向,并且 - 如前所述 - 后面的破折号 (-) 指示 wget 写入标准输出。
  5. 该输出通过管道传送到bunzip2。如果数据流通过管道传输到 Bunzip2,则 Bunzip2 不需要任何附加指令。因此,bunzip2 命令可以紧跟在 wget 命令之后。
  6. Bunzip2 还可以接受 tar 存档作为输入并解压缩其内容。因此,不需要中间的额外步骤。
  7. wget和bunzip2整体做成ssh的命令参数,用引号括起来。
  8. 然后,整个输出通过管道传送到本地计算机上的 tar。同样,因为 tar 默认情况下从 stin 获取输入,所以除了 extract 选项之外没有其他选项。

补充:
在我之前的回答中,我没有完全理解这个问题。我将其留在这里供那些想要从本地计算机下载并提取远程计算机上的存档的人使用,最有效的方法是:

you@local ssh <remote> "wget -qO - https://url.to.my/archive.tar.bz2 | tar xj" 

在上面的示例中,文件被提取到远程计算机上的主目录中,其目录结构与它们放入 tar 中的目录结构相同。你可以改变这一点 -到远程上的现有文件夹- 类似的东西:

you@local ssh <remote> "wget -qO - https://url.to.my/archive.tar.bz2 | tar xjC <destination/dir>" 

答案2

您需要 tar 才能在本地运行; tar -O 基本上cat只是文件内容,因此不适合从中重新创建文件。您可以远程运行bunzip2以利用快速远程CPU - 只需记住,现在所有数据在发送回本地计算机时都已解压缩,因此,如果带宽成为您的首要任务,您可能会损失因更快解压缩而节省的任何时间。限制因素。两种方法都尝试一下,看看吧!无论如何,在 wget 之后..

# do the bunzip2 from the ssh, then pass the output to (local) tar to extract the files on the local system:
ssh $1@$2 'bunzip2 < archive.tar.bz2'|tar -x

答案3

解压存档的方式tar如下:-x=extract、-j=decompress-with-bz2 和 -f=filename。你会这样写

#!/bin/bash
ssh $1@$2 'wget https://url.to.my/archive.tar.bz2'
ssh $1@$2 'tar -xjf archive.tar.bz2'

这有点冒险,因为wget可能会将您的文件保存为另一个名称,例如archive.tar.bz2.1' if a file with the same name already exists. Usewget -Ofixedname.tar.bz2 ...` 以获得确定性输出。

请注意,“tar”是一种流格式(与 zip 不同),它允许您不存储存档并即时解压缩 - 使用更少的磁盘空间和 IO 操作:

ssh $1@$2 'wget -O- https://url.to.my/archive.tar.bz2 |tar -xj'

请注意,我删除了“-f”,因为没有文件名,数据从“管道”之前的 wget 流出。有些内容仍会通过 stderr 打印在您的终端上,wget -qO-如果您愿意,请尝试更安静的操作。请注意,如果发生错误,它们仍会被打印,但前提是发生错误。这就是 Unix 的口头禅:如果一切顺利,就不要提及它。

相关内容