在自己内部过滤shell脚本输出,脚本不会被终止

我想要一个Bash脚本来生成一些输出消息。 该脚本应该捕获消息,做一些过滤,转换,然后输出到屏幕上。

筛选结果在输出中是正确的,但脚本不会终止。 我必须按回车键来完成它。 我如何解决它?

演示脚本:

#!/bin/bash exec &> >( { while read line; do [ "$line" = "exit" ] && break echo "`date +%H:%M:%S.%N` $line" done echo "while finish" } ) for ((i=3;i--;)); do echo "text $i" done echo "exit" 

该脚本终止,但是脚本本身在写入输出的后台进程之前完成,所以首先显示提示符, 然后显示输出,让终端看起来像脚本仍在运行的空白行。 你可以输入任何命令而不是返回,并执行该命令。

为了避免这种情况,您需要在退出脚本之前在显式后台作业中运行while循环。

 mkfifo logpipe trap 'wait $logger_pid; rm logpipe' EXIT while read line; do [ "$line" = "exit" ] && break echo "$(date +%H:%M:%S.%N) $line" done < logpipe & logger_pid=$! exec &> logpipe # ========== for ((i=3;i--;)); do echo "text $i" done echo "exit" 

while循环在后台运行,从命名管道logpipe读取输入。 一旦运行,您可以将所有输出重定向到管道并启动“主”脚本。 退出陷阱确保您的脚本实际上不会退出,直到while循环完成; 它也为您清理命名管道。


您可能还没有注意到,但不能保证while循环将按照写入它们的确切顺序接收合并的标准输出和标准错误。 例如,

 echo out1 echo err1 >&2 echo out2 echo err2 >&2 

可能最终被认为是

 out1 err1 err2 out2 

每个流本身将保持秩序,但可以任意合并。