Убить процесс через заданное время? - PullRequest
28 голосов
/ 21 октября 2011

У меня есть скрипт, который пытается установить соединение с БД с помощью другой программы, и время ожидания (2,5 мин) программы слишком велико.Я хочу добавить эту функцию в сценарий.

Если для подключения требуется больше 5 секунд, завершите процесс
В противном случае завершите процесс sleep / kill.

Проблема I 'Я имею в виду то, как bash сообщает, когда процесс убит, потому что процессы находятся в одной оболочке только в фоновом режиме.Есть ли лучший способ сделать это или как я могу отключить оболочку для команд kill?

DB_CONNECTION_PROGRAM > $CONNECTFILE &
pid=$! 
(sleep 5; kill $pid) &
sleep_pid=$!
wait $pid

# If the DB failed to connect after 5 seconds and was killed
status=$? #Kill returns 128+n (fatal error)
if [ $status -gt 128 ]; then
    no_connection="ERROR: Timeout while trying to connect to $dbserver"
else # If it connected kill the sleep and any errors collect
    kill $sleep_pid
    no_connection=`sed -n '/^ERROR:/,$p' $CONNECTFILE`
fi

Ответы [ 5 ]

108 голосов
/ 22 октября 2011

Существует утилита GNU coreutils, которая называется timeout: http://www.gnu.org/s/coreutils/manual/html_node/timeout-invocation.html

Если у вас есть это на вашей платформе, вы можете сделать:

timeout 5 CONNECT_TO_DB
if [ $? -eq 124 ]; then
    # Timeout occurred
else
    # No hang
fi
10 голосов
/ 22 октября 2011

Не знаю, идентично ли это, но я исправил подобную проблему несколько лет назад. Однако я программист, а не Unix-подобный системный администратор, поэтому примите следующее с долей соли, потому что мой Bash-fu может быть не таким сильным ...

В основном я делал форк, форк и вилку:)

Недостаточно памяти После восстановления моего старого кода (который я удивительно продолжаю использовать ежедневно), потому что моя память была недостаточно хороша, в Bash она работала примерно так:

commandThatMayHang.sh 2 > /dev/null 2>&1 &    (notice that last '&', we're forking)
MAYBE_HUNG_PID=$!
sleepAndMaybeKill.sh $MAYBE_HUNG_PID 2 > /dev/null 2>&1 &   (we're forking again)
SLEEP_AND_MAYBE_KILL_PID=$!   
wait $MAYBE_HUNG_PID > /dev/null 2>&1
if [ $? -eq 0 ]
    # commandThatMayHand.sh did not hang, fine, no need to monitor it anymore
    kill -9 $SLEEP_AND_MAYBE_KILL 2> /dev/null 2>&1
fi

где sleepAndMaybeKill.sh спит необходимое количество раз, а затем убивает commandThatMayHand.sh .

Итак, в основном это два сценария:

  1. ваша команда нормально завершает работу (до истечения 5-секундного тайм-аута или чего-либо еще), поэтому wait останавливается, как только ваша команда завершает работу нормально (и убивает «убийцу», потому что она больше не нужна

  2. команда блокируется, убийца заканчивает тем, что убивает команду

В любом случае вы гарантированно либо преуспеете, как только команда будет выполнена, либо потерпите неудачу после истечения времени ожидания.

0 голосов
/ 27 мая 2019

Вы можете установить тайм-аут через 2 часа и перезапустить ваш javaScriptThatStalls 100 раз таким образом в цикле

seq 100|xargs -II timeout $((2 * 60 * 60)) javaScriptThatStalls
0 голосов
/ 29 марта 2013

Я нашел этот скрипт bash timeout.sh Энтони Тиссена ( его сеть ).Выглядит хорошо.

0 голосов
/ 21 октября 2011

Вы хотите сказать, что не хотите печатать сообщение об ошибке, если процесс еще не запущен? Тогда вы можете просто перенаправить stderr: kill $pid 2>/dev/null.

Вы также можете проверить, запущен ли процесс:

if ps -p $pid >/dev/null; then kill $pid; fi
...