хороший способ убить трубопроводный процесс? - PullRequest
0 голосов
/ 22 февраля 2012

Я хочу обработать каждую строку stdout для оболочки в момент ее создания.Я хочу получить вывод 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;

Но, к сожалению, это напечатает «выход» и затем подождет, так как tail -f все еще работает.Я попробовал и break, и exit

Я запускаю это на FreeBSD, поэтому я не могу использовать опцию --pid= некоторых хвостов Linux.

Я могу использовать ps и grep достать кусочек хвоста и убить его, но мне это кажется очень уродливым.

Есть какие-нибудь намеки?

1 Ответ

2 голосов
/ 22 февраля 2012

зачем вам нужен процесс 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

Однако следует отметить, что такое решение представляет несколько серьезных проблем состояния гонки:

  • PID test.sh может быть повторно использован другим процессом;
  • , если процесс test.sh все еще жив, когда вы читаете последнюю строку, у вас не будет другого случая обнаружить его смерть впоследствии, и ваш цикл будет зависать.
...