【问题标题】:nice way to kill piped process?杀死管道进程的好方法?
【发布时间】:2012-02-22 15:38:18
【问题描述】:

我想在创建 shell 的那一刻处理每个标准输出行。我想获取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;

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

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

我可以使用psgrep 来获取尾巴的pid 并杀死它,但这对我来说似乎很丑。

有什么提示吗?

【问题讨论】:

    标签: shell process pid tail sh


    【解决方案1】:

    为什么需要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:

    ./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 进程在您阅读最后一行时仍然处于活动状态,那么之后您将没有任何其他机会检测到它的死亡并且您的循环将挂起。

    【讨论】:

    • 我现在觉得很愚蠢,因为第一个解决方案显然有效。我对 shell 脚本比较陌生,并没有意识到你提到的第一个解决方案不会阻塞.. 谢谢!
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多