linux - 在 BASH 中使用 PIPESTATUS 有什么问题?

标签 linux bash pipe

我有一个 for 循环,我通过 ssh 将其传递到格式化为看起来有点像这样的服务器......

i=0
for cmd in cmd_list;
do ${cmd} | sed "s/^/OUTPUT_${i}_: /" &
(( i++ ));
done;
wait

这个想法是 for 循环将运行我给它的命令列表,并将每个命令通过管道传递给 sed,其中 sed 在每行输出前加上一个命令编号(0、1、2、3 等... ).然后它返回后台以允许并行执行。这使我能够跟踪输出与哪个命令相关联,因为数据可以同时返回并且全部混合在一起。这真的很好用。根据命令打印信息的时间以及它们完成的时间,输出可能看起来像这样......

OUTPUT_0_: some_data_string_from_a_command
OUTPUT_2_: some_data_string_from_a_command
OUTPUT_0_: some_data_string_from_a_command
OUTPUT_3_: some_data_string_from_a_command
OUTPUT_1_: some_data_string_from_a_command
OUTPUT_1_: some_data_string_from_a_command

然而,我真正想做的是...

do ${cmd} 2>&1 | sed "s/^/OUTPUT_${i}_${PIPESTATUS[0]}: /" &

所以我可以取回这个...

OUTPUT_0_0: some_data_string_from_a_command
OUTPUT_2_1: some_error_message_from_a_command
OUTPUT_0_0: some_data_string_from_a_command
OUTPUT_3_1: some_error_message_from_a_command
OUTPUT_1_0: some_data_string_from_a_command
OUTPUT_1_0: some_data_string_from_a_command

如果第一个命令出错,这在第一个命令上工作正常。我通常会从 ${PIPESTATUS[0]} 获得非零退出代码。但是,当我有目的地在我知道会失败的列表中进一步植入命令时(即 cat/tmp/some_non_existent_file),PIPESTATUS 不会给我管道链中命令的正确退出代码。有时我会得到 0 而不是真正的退出代码。

知道这是为什么吗?

最佳答案

管道中的命令是并行执行的。这意味着它们可能在您评估 PIPESTATUS 时还没有退出,特别是因为 PIPESTATUS 在 sed 命令实际运行之前由 shell 展开。

我真的不明白你想做什么,因为你似乎想违反因果关系。你仔细考虑过吗?你似乎想要一个命令的退出值及其输出,但如果它正在输出数据,它显然还没有退出。您依赖于始终打开的小计时窗口。它可能适用于一些短运行时间的命令,但这甚至是有问题的,因为在没有同步操作的情况下协调并行执行很容易出现“随机”失败。

如果你想捕获数据以及命令的输出状态,你需要将输出保存在某个地方(例如在文件中),当进程退出时,然后用 exit 输出数据状态。

关于linux - 在 BASH 中使用 PIPESTATUS 有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3851699/

相关文章:

linux - Makefile 缺少分隔符

Linux bash 脚本 : share variable among terminal windows

Linux:tail -f 多个选项

mysql - 选择一个字段并将其通过管道传递到其他程序

与 Shell 交互时的 PHP 行为

linux - 将文本处理命令的结果转发到 .ods 文件中的特定位置

windows - 管道 findstr 的输出

带 pipe 和 fork 的 C 作业

linux - Kubernetes Pod : Failed to get D-Bus Connection

java - 从 java 运行 Bash 不起作用