Проходная труба с таймаутом

Решение с использованием команды SED без сценария

Вот и вы:

sed 's / \ * \ // \ n & / g' test | sed '/\/\*/,/\*\//d'

N.B. Это не работает в OS X, если вы не установите gnu-sed . Но он работает в дистрибутивах Linux.

3
18.11.2016, 08:46
3 ответа

Для начала, конвейер сторожевого пса из вашего вопроса, вероятно, не убьет 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`)
2
27.01.2020, 21:26

Альтернативный взгляд на проблему может заключаться в том, чтобы удалить сторожевой таймер из канала и зафиксировать канал на время его последней модификации. Например,

(
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, которые вместо этого.

0
27.01.2020, 21:26

Это может быть неидеальным с точки зрения производительности и зависит от линии, но для этого можно использовать функцию тайм-аута команды read . В bash вы можете затем использовать раздел командной строки, подобный следующему, как часть watchdog --timeout 60 :

while read -r -s -t 60 line ; do printf "%s\n" "$line" ; done

zsh предлагает аналогичное чтение команда.

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

0
27.01.2020, 21:26

Теги

Похожие вопросы