是否可以仅在出现错误时进行管道传输?

是否可以仅在出现错误时进行管道传输?

如果有任何错误,则 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_programfilter_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

相关内容