Вот и вы:
sed 's / \ * \ // \ n & / g' test | sed '/\/\*/,/\*\//d'
N.B. Это не работает в OS X, если вы не установите gnu-sed
. Но он работает в дистрибутивах Linux.
Для начала, конвейер сторожевого пса из вашего вопроса, вероятно, не убьет process1
, если он снова не пытается писать на мертвую трубу. Поэтому ваш сторожевой пёс должен каким-то образом явно убить процесс1.
В дополнение к этому вот очень простой watchdog.sh
сценарий оболочки. Вы можете проверить его в интерактивном режиме в консоли. Просто введите ./watchdog.sh
. Он будет дублировать все, что вы вводите, и остановится, если вы ничего не введете в течение 5 секунд.
#!/bin/bash
# first arg is timeout (default: 5)
T="${1:-5}"
PID=$$
exec tee >(bash -c '
while true ; do
bytes=$(timeout '$T' cat | wc -c)
if ! [ "$bytes" -gt 0 ] ;then
break
fi
done
## add something like "killall process1", for now we just kill this tee command
kill -9 '$PID)
Заметьте, что скрипт на самом деле будет иметь таймаут между T и 2*T (иначе это было бы намного сложнее). Каким-то образом можно добавить способ убить process1
, как я уже говорил.
Ниже пример для тестирования.
process1.sh:
#!/bin/bash
echo "here we are ..."
sleep 2
echo "still alive ..."
sleep 20
echo "too late ..."
И запустите его следующим образом (включая уродливый способ убить process1.sh по таймауту):
(./process1.sh & echo $! >/tmp/pid; wait) |(./watchdog.sh 5; kill `cat /tmp/pid`)
Альтернативный взгляд на проблему может заключаться в том, чтобы удалить сторожевой таймер из канала и зафиксировать канал на время его последней модификации. Например,
(
process1 &
pid=$!
old=0
while new=$(stat -L /dev/stderr -c %Y)
[ $new != $old ]
do old=$new
sleep 60
done 3>&2 2>&1 1>&3 && kill -hup $pid
) |
process2
Это помещает процесс 1 в фоновый режим, чтобы мы могли получить его pid, затем опрашивает время последней модификации выходного канала. Если он не изменится в течение 60 секунд, мы можем убить pid. Чтобы иметь возможность захватывать вывод stat
, мы меняем местами дескриптор файла 1, который является конвейером, на stderr и stat, которые вместо этого.
Это может быть неидеальным с точки зрения производительности и зависит от линии, но для этого можно использовать функцию тайм-аута команды read
. В bash
вы можете затем использовать раздел командной строки, подобный следующему, как часть watchdog --timeout 60
:
while read -r -s -t 60 line ; do printf "%s\n" "$line" ; done
zsh
предлагает аналогичное чтение
команда.
Однако обратите внимание, что на самом деле он не завершит выполнение всей команды до тех пор, пока первая часть, то есть ваш process1
, не решит завершить работу из-за закрытия стандартного вывода.