我想使用 tar 和 ssh 在 ubuntu 14.04 上作为自动化流程的一部分发送文件。我可以按如下方式发送文件:
tar -c large_test_file_10MB.txt.tar.gz | ssh -q 172.16.200.211 'tar -x'
但这不允许我监控传输进度。我已设法将文件打包,并使用以下命令将进度写入 stdout:
tar -czf large_test_file_10MB.txt.tar.gz large_test_file_10MB.txt --record-size=10K --checkpoint=100 --checkpoint-action=exec='echo $TAR_CHECKPOINT"0kiB"'; FROMSIZE=`du -sk large_test_file_10MB.txt | cut -f 1`; printf "%dkiB\n" $FROMSIZE
它产生以下输出:
1000kiB
2000kiB
3000kiB
4000kiB
5000kiB
6000kiB
7000kiB
8000kiB
9000kiB
9768kiB
但这不允许我将文件传输到 ssh 并同时查看进度。如果我将 --checkpoint-action=exec 命令从
echo $TAR_CHECKPOINT"0kiB"
到
echo $TAR_CHECKPOINT"0kiB" >> progress.txt
输出变为
1000kiB >> progress.txt
2000kiB >> progress.txt
3000kiB >> progress.txt
4000kiB >> progress.txt
5000kiB >> progress.txt
6000kiB >> progress.txt
7000kiB >> progress.txt
8000kiB >> progress.txt
9000kiB >> progress.txt
9768kiB >> progress.txt
我怎样才能让 --checkpoint-action=exec 命令写入文件而不是标准输出?
我知道我可以使用诸如 pv 之类的工具来执行此操作,但我希望能够在不安装其他软件的情况下运行该命令。
答案1
从手册上看,它似乎tar
没有调用 shell,而是自己对参数执行一些字段拆分和扩展exec
。从运行外部命令:
某些 GNU tar 操作意味着运行您在命令行中提供的外部命令。其中一个操作是检查点,如上所述 [...]
每当请求此类操作时,
tar
首先将提供的命令拆分为单词,就像 shell 所做的那样。然后它将第一个单词视为要执行的程序或 shell 脚本的名称,其余单词视为其命令行参数。除非以绝对文件名给出,否则将在 shell 的 中搜索该程序PATH
。任何附加信息通常以环境变量的形式提供给外部命令,特定于每个特定操作。例如,选项
--checkpoint-action=exec
将TAR_ARCHIVE
变量定义为正在处理的档案的名称。如果需要,您可以在外部命令的命令行中使用这些变量。
因此,如果您需要其他 shell 语法(如重定向),则需要调用 shell:
tar ... --checkpoint-action=exec='sh -c "echo $TAR_CHECKPOINT"0kiB" >> progress.txt"'
(奇怪的引用有效:sh
仍然应该得到一个字符串echo [...]0kiB > progress.txt
作为后面的参数-c
。)