杀死管道进程的好方法?

时间:2012-02-22 15:38:18

标签: shell process pid tail sh

我希望在创建shell时处理shell的每个stdout-line。我想获取test.sh的输出(一个很长的过程)。我目前的做法是:

 ./test.sh >tmp.txt &
 PID=$!
 tail -f tmp.txt | while read line;  do
 echo $line
 ps ${PID} > /dev/null
 if [ $? -ne 0 ]; then
     echo "exiting.."
 fi
 done;

但不幸的是,这将打印“退出”然后等待,因为尾部-f仍在运行。我尝试了breakexit

我在FreeBSD上运行它,所以我不能使用某些linux尾部的--pid=选项。

我可以使用psgrep获取尾部的pid并将其杀死,但这对我来说似乎非常难看。

任何提示?

1 个答案:

答案 0 :(得分:2)

为什么需要tail流程?

你能不能按照

的方式做点什么
./test.sh | while read line; do
  # process $line
done

或者,如果你想保持输出在tmp.txt:

./test.sh | tee tmp.txt | while read line; do
  # process $line
done

如果您仍想使用中间tail -f进程,也许您可​​以使用命名管道(fifo)而不是常规管道,以允许分离tail进程并获取其pid:< / p>

./test.sh >tmp.txt &
PID=$!

mkfifo tmp.fifo
tail -f tmp.txt >tmp.fifo &
PID_OF_TAIL=$!
while read line; do
  # process $line
  kill -0 ${PID} >/dev/null || kill ${PID_OF_TAIL}
done <tmp.fifo
rm tmp.fifo
然而,我应该提到这样的解决方案存在几个严重的竞争条件问题:

  • test.sh的PID可以被其他进程重用;
  • 如果test.sh进程在您读完最后一行时仍处于活动状态,则之后您将无法再检测到其死亡,并且您的循环将会挂起。