У меня есть сценарий Python, который будет проверять очередь и выполнять действия для каждого элемента:
# checkqueue.py
while True:
check_queue()
do_something()
Как мне написать bash-скрипт, который проверит, работает ли он, а если нет, запустите его. Примерно следующий псевдокод (или, может быть, он должен что-то вроде ps | grep
?):
# keepalivescript.sh
if processidfile exists:
if processid is running:
exit, all ok
run checkqueue.py
write processid to processidfile
Я позвоню из crontab:
# crontab
*/5 * * * * /path/to/keepalivescript.sh
Ответы:
Избегайте PID-файлов, cron или чего-либо еще, что пытается оценить процессы, которые не являются их дочерними.
Есть очень веская причина, почему в UNIX вы можете ТОЛЬКО ждать своих детей. Любой метод (ps parsing, pgrep, хранение PID, ...), который пытается обойти проблему, имеет недостатки и имеет зияющие дыры в нем. Просто скажи нет .
Вместо этого вам нужен процесс, который контролирует ваш процесс, чтобы быть его родителем. Что это значит? Это означает, что только процесс, который запускает ваш процесс, может надежно ожидать его завершения. В bash это абсолютно тривиально.
Приведенный выше фрагмент кода bash выполняется
myserver
вuntil
цикле. Первая строка начинаетсяmyserver
и ждет окончания. Когда он заканчивается,until
проверяет его статус выхода. Если статус выхода -0
это означает, что он закончился изящно (что означает, что вы попросили его как-то отключиться, и он сделал это успешно). В этом случае мы не хотим перезапускать его (мы просто попросили его выключить!). Если состояние выхода не является0
,until
запустится тело цикла, которое выдает сообщение об ошибке на STDERR и перезапускает цикл (обратно к строке 1) через 1 секунду .Почему мы ждем секунду? Потому что, если что-то не так с последовательностью запуска
myserver
и она сразу падает, у вас будет очень интенсивный цикл постоянного перезапуска и сбоя в ваших руках. Этоsleep 1
снимает напряжение с этого.Теперь все, что вам нужно сделать, это запустить скрипт bash (вероятно, асинхронно), и он будет отслеживать
myserver
и перезапускать его по мере необходимости. Если вы хотите запустить монитор при загрузке (заставляя сервер «выживать», перезагружается), вы можете запланировать его в cron (1) вашего пользователя с помощью@reboot
правила. Откройте свои правила cron с помощьюcrontab
:Затем добавьте правило для запуска скрипта монитора:
В качестве альтернативы; посмотрите на inittab (5) и / etc / inittab. Вы можете добавить туда строку, чтобы
myserver
начать с определенного уровня инициации и автоматически возродиться.Редактировать.
Позвольте мне добавить информацию о том, почему бы не использовать файлы PID. Пока они очень популярны; они также очень несовершенны, и нет никаких причин, по которым вы бы просто не сделали это правильно.
Учти это:
Утилизация ПИД (убивает неправильный процесс):
/etc/init.d/foo start
: начатьfoo
, написатьfoo
PID для/var/run/foo.pid
foo
умирает как-то.bar
), берет случайный PID, представьте, что он используетfoo
старый PID.foo
что ушел:/etc/init.d/foo/restart
читает/var/run/foo.pid
, проверяет, если он все еще жив, находитbar
, думает, что этоfoo
, убивает его, начинает новыйfoo
.PID файлы устарели. Вам нужна слишком сложная (или, я бы сказал, нетривиальная) логика, чтобы проверить, не устарел ли файл PID, и любая ли такая логика снова уязвима для
1.
.Что если у вас даже нет прав на запись или вы находитесь в среде только для чтения?
Это бессмысленное чрезмерное усложнение; Посмотрите, насколько простой мой пример выше. Нет необходимости усложнять это вообще.
Смотрите также: PID-файлы все еще имеют недостатки, когда делают это «правильно»?
Кстати; разбирается даже хуже, чем PID-файлы
ps
! Никогда не делай этого.ps
очень непереносимо. В то время как вы найдете его почти в каждой системе UNIX; его аргументы сильно различаются, если вы хотите нестандартный вывод. И стандартный вывод предназначен ТОЛЬКО для потребления человеком, а не для синтаксического анализа!ps
приводит к большому количеству ложных срабатываний. Возьмитеps aux | grep PID
пример, и теперь представьте, что кто-то начинает процесс с номером где-то в качестве аргумента, который совпадает с PID, с которым вы смотрели своего демона! Представьте, что два человека начинают сеанс Х, и вы ищете, чтобы Х убил ваш. Это просто все виды плохого.Если вы не хотите сами управлять процессом; Есть несколько совершенно хороших систем, которые будут выполнять функции мониторинга ваших процессов. Посмотрите в рунит , например.
источник
while true; do myprocess; done
но учтите, что теперь нет способа остановить процесс.trap 'kill $(jobs -p)' EXIT; until myserver & wait; do sleep 1; done
Посмотрите на monit ( http://mmonit.com/monit/ ). Он обрабатывает запуск, остановку и перезапуск вашего скрипта и может выполнять проверки работоспособности и перезапускать при необходимости.
Или сделайте простой скрипт:
источник
Самый простой способ сделать это - использовать flock on file. В скрипте Python вы бы сделали
В оболочке вы можете проверить, работает ли он:
Но, конечно, вам не нужно тестировать, потому что, если он уже запущен и вы перезапустите его, он завершится с
'other instance already running'
Когда процесс умирает, все его файловые дескрипторы закрываются и все блокировки автоматически снимаются.
источник
flock
... на самом деле, страница руководства явно демонстрирует как!exec {lock_fd}>/tmp/script.lock; flock -x "$lock_fd"
является bash-эквивалентом вашего Python и оставляет блокировку удержанной (поэтому, если вы затем выполняете процесс, блокировка будет удерживаться до завершения этого процесса).flock
- правильный путь, но ваши сценарии неверны. Единственная команда, которую вам нужно установить в crontab:flock -n /tmp/script.lock -c '/path/to/my/script.py'
Вы должны использовать monit, стандартный инструмент Unix, который может отслеживать различные вещи в системе и реагировать соответствующим образом.
Из документов: http://mmonit.com/monit/documentation/monit.html#pid_testing
Вы также можете настроить monit, чтобы он отправлял вам электронное письмо при перезагрузке.
источник
источник
ps ax|grep ...
. Вы можете просто установить его или написать для этого функцию: function psgrep () {ps ax | grep -v grep | grep -q "$ 1"}Я не уверен, насколько она переносима между операционными системами, но вы можете проверить, содержит ли ваша система команду «run-one», то есть «man run-one». В частности, этот набор команд включает в себя «run-one-постоянно», что, кажется, именно то, что нужно.
С man-страницы:
Примечание: очевидно, что это может быть вызвано из вашего скрипта, но это также устраняет необходимость иметь скрипт вообще.
источник
Я использовал следующий скрипт с большим успехом на многочисленных серверах:
ноты:
$INSTALLATION
содержит достаточно пути процесса, это совершенно однозначноЭтот сценарий фактически используется для закрытия работающего экземпляра tomcat, который я хочу завершить (и ждать) в командной строке, поэтому запуск его как дочернего процесса просто не подходит для меня.
источник
grep | awk
все еще антипаттерн - хочешьawk "/$INSTALLATION/ { print \$1 }"
отождествлять бесполезноеgrep
в скрипт Awk, который может очень хорошо находить строки по самому регулярному выражению, большое спасибо.Я использую это для моего процесса npm
источник