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

Posted

技术标签:

【中文标题】在 cloud-init 过程中显示 scp 的进度【英文标题】:Showing progress of scp during cloud-init process 【发布时间】:2022-01-11 18:32:34 【问题描述】:

当我启动一个新服务器时,我使用一个 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 进程替换”变体而不是“管道”变体的进度确实显示...但是当跟踪 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 如果 stdout 不是 TTY(您的文件不是),则关闭进度表。看起来你可以通过使用script(或在 PTY 下运行程序的其他东西)来说服它输出是 TTY,请参阅***.com/a/1402389 天才@Hasturkun!我不知道一个命令可以像这样改变它的输出,没有一个明确的选项!仅供参考,this answer 中的辅助功能对我很有帮助,按照评论中的建议添加了-e 选项...所以我可以在正常命令前加上辅助功能:fake_tty scp myuser@123.45.6.789:path/to/file.tar.gz >(tar -zx) >output.log 2>&1,现在可以看到进度在output.log! (我认为它在实际的 cloud-init 中会起作用,但我还没有尝试过)。如果您发布答案,我会接受...谢谢! OK 修改...它没有 -e 选项...即仅script -qfc(完全按照linked answer)...使用script -qfce 的某些原因给出了No such file or directory error 您可能想要使用-qfec,因为-c 需要一个参数(所以我认为将e 作为一个参数)。我认为如果我将其标记为另一个的副本会更好(因为我在这里唯一的贡献是scp 不会进展到非 TTY 的事实),而不是做一个链接 - 主要是答案。 啊,是的,您对 qfec 的命令是正确的...有效。我不确定这是否真的是重复的……这是一种新的教学,即 scp 将进度表禁用为非 TTY,即使(一旦你知道)答案与另一个相同。 IE。不同的问题,相同的答案。 【参考方案1】:

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

您可以通过在script(如in this answer 所示)或任何其他运行程序并将其输出连接到PTY。

【讨论】:

谢谢!作为奖励点,您能解释一下为什么在script -qfc "$(printf "%q " "$@")" /dev/null 中的%q 之后需要一个空格吗? 没有空格参数会粘在一起,因为bash printf 重用所有参数的格式。 啊,好的,我知道它在做什么了。最后一个参数的末尾有一个空格,但我想这无关紧要。

以上是关于在 cloud-init 过程中显示 scp 的进度的主要内容,如果未能解决你的问题,请参考以下文章

云服务器cloud-init初始化工具的使用与配置

在本地KVM中使用cloud-init

scp 拷贝远端文件失败

Linux之scp命令

是否可以让 SCP 在复制过程中忽略符号链接?

Dcmtk 源码解读SCP交互过程- CEcho Scp