[英]How to monitor progress of ssh file transfer and output to a log file
我正在编写一个bash脚本来定期将数据传输到远程系统。 我有一个生成流的本地命令,以及一个使用它的远程命令,所以我做的是这样的:
generate_data | ssh remoteserver.example.com consume_data
(我设置了ssh键,所以我可以非交互式地执行此操作。)这很好用。 但是,由于这将是一个自动化过程(作为一个cron作业运行),有时可能会在有限的带宽上传输大量数据,我希望能够在我的日志文件中定期进行更新。 我原本以为使用pv
(管道查看器),这是我能想到的最好的:
generate_data | pv -fb | ssh remoteserver.example.com consume_data
再次,它的工作原理...... 但是 pv真的是用终端输出编写的,所以我最终在日志中看起来很乱
2.06MB^M2.19MB^M2.37MB^M 2.5MB^M2.62MB^M2.87MB^M3MB^M3.12MB^M3.37MB
我更喜欢日志消息
<timestamp> 2.04MB transferred...
<timestamp> 3.08MB transferred...
如果有人对如何做到这一点有任何聪明的想法,无论是对pv
不同论点还是通过其他机制,我都会感激不尽。
编辑:感谢您的答案到目前为止。 当然,有很多可能的家庭酿造解决方案; 我希望找到一些可以“开箱即用”的东西。 (并不是说我排除了自酿;这可能是最简单的事情。由于pv
已经达到了我所需要的98%,我宁愿不重新发明它。)
PostScript:这是我最终使用的那条线,希望它可能在某些时候帮助别人。
{ generate_data | pv -fbt -i 60 2>&3 | ssh remoteserver consume_data } 3>&1 | awk -vRS='\r' '{print $1 " transferred in " $2; fflush();}' >> logfile
如果你想坚持使用pv
,你可以稍微后处理它的输出。 至少将CR转换为LF。
{ generate_data | pv -bft 2>&3 | consume_data >/dev/null; } 3>&1 | tr '\015' '\012'
使用awk进行更高级的处理。
{ generate_data | pv -bft 2>&3 | consume_data >/dev/null; } 3>&1 |
awk -vRS='\r' '{print $2, $1 " transferred"}'
但请记住,标准文本处理实用程序只有在打印到终端时才会在每行末尾刷新输出。 因此,如果您将pv
传输到其输出转到管道或文件的其他实用程序,则由于缓冲将会出现不可忽略的延迟。 如果您有GNU awk或其他具有fflush
功能的实现(这是常见的但不是标准的),请使其在每行上刷新其输出:
{ generate_data | pv -bft 2>&3 | consume_data >/dev/null; } 3>&1 |
awk -vRS='\r' '{print $2, $1 " transferred"; fflush()}'
这是一个小红宝石脚本,我相信你想要的。 由于ruby的开销,我每秒只能获得大约1MB的文件复制到本地文件系统,但是你提到管道的带宽有限,所以这可能没问题。 我从rails(actionview)中提取了number_to_human_size函数。
#!/usr/bin/ruby
require 'rubygems'
require 'active_support'
# File vendor/rails/actionpack/lib/action_view/helpers/number_helper.rb, line 87
def number_to_human_size(size)
case
when size < 1.kilobyte: '%d Bytes' % size
when size < 1.megabyte: '%.1f KB' % (size / 1.0.kilobyte)
when size < 1.gigabyte: '%.1f MB' % (size / 1.0.megabyte)
when size < 1.terabyte: '%.1f GB' % (size / 1.0.gigabyte)
else '%.1f TB' % (size / 1.0.terabyte)
end.sub('.0', '')
rescue
nil
end
UPDATE_FREQ = 2
count = 0
time1 = Time.now
while (!STDIN.eof?)
b = STDIN.getc
count += 1
print b.chr
time2 = Time.now
if time2 - time1 > UPDATE_FREQ
time1 = time2
STDERR.puts "#{time2} #{number_to_human_size(count)} transferred..."
end
end
你可以看看吧: http : //clpbar.sourceforge.net/
Bar是一个简单的工具,用于复制数据流并在stderr上为用户打印显示,显示(a)传递的数据量,(b)数据传输的吞吐量,以及(c)传输时间,或者,如果已知数据流的总大小,则估计剩余时间,已完成数据传输的百分比以及进度条。
Bar最初是为了估计在网络上传输大量(许多,几千兆字节)数据所需的时间而编写的。 (通常在SSH / tar管道中。)
源代码位于http://code.google.com/p/pipeviewer/source/checkout,因此您可以编辑一些C并使用PV!
编辑:是的获取源然后编辑display.c的第578行,其中有这个代码:
display = pv__format(&state, esec, sl, tot);
if (display == NULL)
return;
if (opts->numeric) {
write(STDERR_FILENO, display, strlen(display)); /* RATS: ignore */
} else if (opts->cursor) {
pv_crs_update(opts, display);
} else {
write(STDERR_FILENO, display, strlen(display)); /* RATS: ignore */
write(STDERR_FILENO, "\r", 1);
}
您可以将“\\ r”更改为“\\ n”并重新编译。 通过每次将它放在一个新行上,这可以为您提供更有用的输出。 如果需要,您也可以尝试重新格式化整个输出字符串。
也许是一个小的perl程序将STDIN复制到STDOUT并将其进度打印到STDERR?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.