我正在运行一个 shell 脚本,将数据从一个进程传输到另一个进程
process_a | process_b
有人知道怎样找出两个程序之间传递了多少字节吗?目前我能想到的唯一解决方案是编写一个小型 c 程序,从 stdin 读取,写入 stdout 并计算所有传输的数据,并将计数存储在环境变量中,例如:
process_a | count_bytes | process_b
有人有更简洁的解决方案吗?
答案1
通过 dd 进行管道传输。dd 的默认输入是 stdin,默认输出是 stdout;当它完成 stdin/stdout I/O 时,它将向 stderr 报告其传输了多少数据。
如果您想要捕获 dd 的输出,并且其他程序已经与 stderr 通信,则使用另一个文件描述符。例如,
$ exec 4>~/fred
$ input-command | dd 2>&4 | output-command
$ exec 4>&-
答案2
使用光伏管道查看器。这是一款很棒的工具。一旦您了解它,您就永远不会知道没有它您该如何生活。
它还可以显示进度条和传输的“速度”。
答案3
process_a | tee >(process_b) | wc --bytes
可能会有效。然后您可以将wc
的计数重定向到您需要的任何地方。如果process_b
将任何内容输出到stdout
/ ,stderr
您可能需要将其重定向到某个地方,只要/dev/null
。
举一个稍微有点不自然的例子:
filestore:~# cat document.odt | tee >(dd of=/dev/null 2>/dev/null) | wc --bytes
4295
解释一下:tee
让你将输出直接发送到多个文件(加上 stdout),>()
构造是 bash 的“进程替换”,这使得进程看起来像一个只写文件,这样你就可以重定向到进程和文件(参见这里, 或者这个问题+答案用于将输出发送到多个进程的示例tee
)。
答案4
我知道我迟到了,但我相信我有一个很好的答案,可以增强这个有用的帖子。
这是@Phil P 和@David Spillett 答案的混合,但是:
- 与@Phil P 不同,它避免创建新文件
- 与@David Spillett 不同,它维护了管道结构
字节数与 process_b 的任何输出一起打印到 stdout。
处理输出时,可以使用前缀来标识包含字节的行(Bytes:
在示例中)。
exec 3>&1
process_a | tee >({ echo -n 'Bytes:'; wc -c; } >&3) | process_b
exec 3>&-
警告:
不要依赖输出中行的顺序。
顺序是不可预测的,并且总是会有所不同,即使使用相同的参数调用相同的脚本!