2

Я хочу определить, когда какой-то процесс застрял, но это не дает мне никаких подсказок по этому вопросу. Все, что я знаю, это то, что если он не выдает никакого вывода в течение заданного времени ожидания (скажем, 30 секунд), это означает, что он, вероятно, заблокирован.

Я знаю программу timeout - аута coreutils, но она основана на полном времени завершения программы, а не на последней строке времени вывода. Я хотел бы, чтобы что-то подобное сработало:

timeout --stdout --stderr 30s my-program

Так есть ли способ сделать это? Как мне это сделать?

3 ответа3

1

Код

Сохраните это как tkill (сделайте его исполняемым и при необходимости настройте PATH ):

#!/bin/bash

_terminate_children() {
        trap "exit 143" SIGTERM && kill -- -$$
}

trap _terminate_children SIGINT SIGTERM

tout="$1"
shift
eval $@ | tee >(while :; do
   read -t "$tout"
   case $? in
      0) : ;;
      1) break ;;
      *) _terminate_children ;;
   esac
done)
exit ${PIPESTATUS[0]}

Основное использование

tkill 30 some_command

Первый аргумент (30 здесь) - это время ожидания в секундах.


Заметки

  • tkill ожидает, что some_command будет генерировать текстовый (не двоичный) вывод.
  • tkill stdout данной команды. Чтобы включить stderr перенаправьте его, как в последнем расширенном примере ниже.

Расширенное использование

Это действительные примеры:

tkill 9 foo -option value
tkill 9 "foo -option value"  # equivalent to the above
tkill 5 "foo | bar"
tkill 5 'foo | bar'
tkill 5 'foo | bar | baz'    # tkill monitors baz
tkill 5 'foo | bar' | baz    # baz reads from tkill
tkill 3 "foo; bar"
tkill 6 "foo && bar || baz"
tkill 7 "some_command 2>&1"

Используйте синтаксис Bash в этих цитатах.


Статус выхода

  • Если some_command завершается сам по себе, то его состояние выхода будет повторно использовано как состояние выхода tkill ; tkill 5 true возвращает 0 ; tkill 5 false возвратов 1 ; tkill 5 "true; false" возвращает 1 .
  • Если указанный тайм-аут истекает или tkill прерывается SIGINT или SIGTERM тогда статус выхода будет 143 .

Фрагменты кода объяснены

  • eval делает возможными расширенные примеры.
  • tee позволяет нам анализировать стандартный stdin , передавая его копию в стандартный stdout .
  • read -t отвечает за применение тайм-аута, его состояние выхода используется для определения того, что делать дальше.
  • Команды, которые отслеживаются, убиваются при необходимости с этим решением .
  • С помощью этого решения можно получить статус выхода отслеживаемой команды.
0

Запустите программу в фоновом режиме, одновременно копируя вывод в файл. Через 30 секунд, если файл пуст, закройте программу, иначе верните ее на передний план.

my-program | tee temp-file & 
sleep 30
[ -s temp-file ] && kill $! || fg $!
0

Итак, в основном примерно так:

#!/bin/bash
tmp1=/tmp/tmp-$$-1
tmp2=/tmp/tmp-$$-2
touch $tmp1
touch $tmp2

time_out=30

typeset -i i

i=0
my-program > $tmp1 &
pgmpid=$!

while ps $pgmpid > /dev/null ; do
    sleep 1
    if diff $tmp1 $tmp2 > /dev/null ; then
        i=i+1
        if [ $i -gt $time_out ] ; then
            kill $pgmpid
        fi
    else
        i=0
        cp $tmp1 $tmp2 
    fi
done

rm -f $tmp1 $tmp2

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .