如果有任何错误,则 2>&1 并通过管道 (|) 到另一个程序,否则不要 2>&1 且不通过管道
答案1
所以你想跑
main_program 2>&1 | filter_program
但只有在返回失败状态filter_program
时才应该运行。main_program
在程序完成执行之前,无法得知程序的状态。因此,要仅在程序失败时处理输出,您需要在程序运行时保存程序的输出,然后在程序完成后,运行输出处理命令或丢弃输出。请注意,在这个答案中,我将使用“输出”来表示 stdout 和 stderr 的组合输出;如果您想单独处理标准输出,可能需要额外的工作。
如果输出很小并且仅是文本,您可以将输出和返回状态保存在 shell 变量中。这不适用于二进制数据(包含空字节的数据),因为大多数 shell 不支持变量中的二进制数据。
error_output=$(main_program 2>&1; echo ".$?")
error_status=${error_output##*.}
error_output=${error_output%.*}
if [ "$error_status" -ne 0 ]; then
printf %s "$error_output" | filter_program
fi
如果输出可能很大或为二进制,请将其保存到临时文件中。
output_file=$(mktemp)
main_program >"$output_file" 2>&1
if [ "$?" -ne 0 ]; then
filter_program <"$output_file"
fi
rm -f -- "$output_file"
(省略:删除信号上临时文件的代码。)
(如果输入来自管道很重要,则替换filter_program <"$output_file"
为。)<"$output_file" cat | filter_program
filter_program
如果主程序仅在失败时产生输出,则可以在过滤器产生输出后立即启动它,而不是等待退出状态。这ifne
效用来自更多实用程序对此很方便。
main_program 2>&1 | ifne filter_program
答案2
您是否正在寻找命名管道像这样:
## Create a named pipe
$ mkfifo errorPipe
## In another shell session, launch whatever program you want to pipe the
## error to, telling it to read from errorPipe
$ errorCommand < errorPipe
##$ wc -l errorPipe
1 errorPipe 运行您的程序,将其 stderr 重定向到命名管道 $ yourCommand 2> errorPipe
这样,只有错误会被传送到errorCommand
.为了显示:
$ mkfifo errorPipe
$ wc -l < errorPipe ## this will hang until I write something to errorPipe
现在,我打开另一个终端并运行:
$ perl -le 'sleep(2);
print "this is stdout";
sleep(2);
print STDERR "this is stderr"' 2>errorPipe
this is stdout
2秒后,我将this is stdout
在当前终端中看到打印内容。同时,wc
我在另一个终端中启动的进程将退出并打印其结果:
$ wc -l errorPipe
1 errorPipe