在 cloud-init 进程中显示 scp 的进度

Showing progress of scp during cloud-init process

当我启动新服务器时,我使用 cloud-init 脚本来自动执行该过程。我通过以下方式关注此过程的进展:

$ tail -f /var/log/cloud-init-output.log

当谈到使用 scp 获取备份文件并通过 tar -zx 管道传输时,我在 cloud-init 脚本中尝试了以下操作:

$ scp myuser@123.45.6.789:path/to/file.tar.gz /dev/stdout | tar -zx

虽然此命令有效,但 scp 输出的方便进度指示不会出现在 tail -f 输出中...即我没有看到进度,如:

file.tar.gz   57%   52MB  25.2MB/s   00:02    

我也尝试过 bash 进程替换,如下所示:

$ scp myuser@123.45.6.789:path/to/file.tar.gz >(tar -zx)

进度指示仍然没有出现在 tail -f 输出中。

如何在 tail -f 输出中保留进度指示?特别是在获取较大的备份文件时要查看进度,保留这些指示会非常方便。

请注意,当我 运行 直接在 bash 脚本中执行上述两个操作时(set -x 在顶部),'bash process substitution' 变体会显示进度但不是 'piping' 变体...但是在拖尾 cloud-init 日志时,两个变体都显示进度。

看起来 cloud-init 只是将 stdoutstderr 从所有 cloud-init 阶段发送到 /var/log/cloud-init-output.log(参见 here)。

所以我们可以通过以下调用重新创建 cloud-init 进程(为了这个问题的目的):

$ scp myuser@123.45.6.789:path/to/file.tar.gz >(tar -zx) >output.log 2>&1

然后我们分别跟踪此日志文件:

$ tail -f output.log

奇怪的是...此 output.log 文件中从未出现任何进度状态。然而进度状态肯定正在发送......以下唯一的变化是指向 /dev/stdout 而不是 output.log:

$ scp myuser@123.45.6.789:path/to/file.tar.gz >(tar -zx) >/dev/stdout 2>&1
file.tar.gz   57%   52MB  25.2MB/s   00:02    

那么,当我们将 stdout 指向 output.log 时,为什么我们在 /dev/stdout 上看到进度状态,而在 output.log 上看不到进度状态?

像其他一些工具一样,scp 检查它的输出是否要发送到 TTY(通过使用 isatty),如果不是则禁用进度表输出(你可以找到类似的情况例如,ls --color=auto 仅在输出到终端时发出颜色代码)。

您可以通过 运行 在 script 下(如 in this answer 所示)或任何其他工具(例如 expect) 运行程序,其输出连接到 PTY。