Как убедиться, что приложение продолжает работать в Linux

83

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

Программист во мне хочет потратить несколько часов на то, чтобы разобраться в проблеме, но занятой человек во мне думает, что должен быть простой способ определить, не запущено ли приложение, и запустить его снова.

Я знаю , что я мог бы хроны-скрипт п.с. через Grep:

ps -A | grep appname

Но опять же, это еще один час моей жизни, потраченный на то, что уже должно существовать ... Разве нет готового приложения, в которое я могу передать исполняемый файл (необязательно с аргументами), и которое будет поддерживать процесс бесконечно?

В случае, если это имеет значение, это Ubuntu.

Оли
источник
1
Это зависит от того, теряется ли статистика, когда скрипт не работает, но я думаю, что программист в вас прав - вы должны узнать больше о том, почему скрипт не продолжается бесконечно.
Джонатан Леффлер
1
Это больше служебная программа по запросу, чем что-то, что постоянно вычисляет цифры. Если произойдет сбой до сохранения данных, ничего не потеряно; он просто завершит задание при следующем запуске.
Оли
Вопрос был дан ответ на стандартный или лучший способ сохранить живой процесс , начатый init.d . Решения включают использование systemd и /etc/inittab.
koppor 08

Ответы:

37

Примечание: Upstart находится в режиме обслуживания и был оставлен Ubuntu, который использует systemd. Чтобы узнать подробности о том, как написать определение службы, следует обратиться к руководству по systemd .

Поскольку вы используете Ubuntu, вас может заинтересовать Upstart , который заменил традиционный sysV init . Одна из ключевых особенностей заключается в том, что он может перезапустить службу, если она неожиданно умирает. Fedora перешла на выскочку, а Debian находится в экспериментальной стадии, так что, возможно, стоит изучить ее.

Однако в данной ситуации это может быть излишним, поскольку для реализации сценария cron потребуется 2 минуты.

#!/bin/bash
if [[ ! `pidof -s yourapp` ]]; then
    invoke-rc.d yourapp start
fi
JimB
источник
Я должен отметить, что настроить выскочку для управления вашей службой и поддержания ее работы довольно просто (вы пишете небольшой файл конфигурации). Это решение намного чище, проще и лучше, чем любой другой «простой» мониторинг на основе скриптов cron / shell.
Thor
@thor - (обратите внимание, это из 2008 года, когда выскочка была новой, а документацию найти было труднее). Я согласен, «простой» скрипт cron был создан для иллюстрации того, что скрипт не должен быть сложным, чтобы выполнять свою работу.
JimB
Понимаю. Я все равно поддержал ваш ответ, когда размещал свой комментарий
Тор,
86

Я использовал простой скрипт с cron, чтобы убедиться, что программа работает. Если это не так, он запустит его. Возможно, это не идеальное решение, которое вы ищете, но оно простое и работает достаточно хорошо.

#!/bin/bash
#make-run.sh
#make sure a process is always running.

export DISPLAY=:0 #needed if you are running a simple gui app.

process=YourProcessName
makerun="/usr/bin/program"

if ps ax | grep -v grep | grep $process > /dev/null
then
    exit
else
    $makerun &
fi

exit

Затем добавляйте задание cron каждую минуту или каждые 5 минут.

Крис Вендт
источник
2
Это гениально. Он переживет перезагрузку и устанавливать нечего.
Ian Purton
Я использовал это сам, потому что для установки не требуются права root.
JohnMudd
Что было process nameбы, если бы я хотел, чтобы скрипт Python продолжал работать?
Пользователь
@User Используйте, ps ax | grep XXXчтобы перечислить только ваш процесс, тогда будет XXX.
strongwillow
11
Как однострочник cron, запускать раз в минуту:* * * * * ps aux|grep -v grep|grep -q YourProcessName || /usr/bin/program &
ACK_stoverflow,
43

Монит для этого идеально подходит :)

Вы можете написать простые файлы конфигурации, которые сообщают monit, что нужно смотреть, например, порт TCP, файл PID и т. Д.

monit выполнит указанную вами команду, когда процесс, который он отслеживает, недоступен / использует слишком много памяти / слишком долго привязан к процессору / и т. д. Также появится уведомление по электронной почте о том, что произошло и можно ли что-нибудь с этим поделать.

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

- Ваш верный сотрудник, Монит

Гарет
источник
19
Как вы поддерживаете работу Monit?
JohnMudd
2
Этому довольно сложно научиться. Я просто хочу перезапустить сценарий (вместо службы), и я часами читал его документ, но не мог понять.
Тайлер Лонг
21

Если вы используете дистрибутив на основе systemd, такой как Fedora и недавние выпуски Ubuntu, вы можете использовать возможность systemd «Restart» для служб. Он может быть настроен как системная служба или как пользовательская служба, если ей нужно управлять и запускать от имени конкретного пользователя, что более вероятно в конкретной ситуации OP.

Вариант перезапуска занимает один из no , on-success, on-failure, on-abnormal, on-watchdog, on-abort, или always.

Чтобы запустить его как пользователь, просто поместите файл, подобный следующему, в ~/.config/systemd/user/something.service:

[Unit]
Description=Something

[Service]
ExecStart=/path/to/something
Restart=on-failure

[Install]
WantedBy=graphical.target

тогда:

systemctl --user daemon-reload
systemctl --user [status|start|stop|restart] something

Никаких прав root / модификации системных файлов, никаких заданий cron, ничего не нужно устанавливать, чертовски гибко (см. Все соответствующие опции сервисов в документации).

См. Также https://wiki.archlinux.org/index.php/Systemd/User для получения дополнительной информации об использовании экземпляра systemd для каждого пользователя.

Раман
источник
Отличный ответ, но ~ / .config / systemd / user / something.service для меня был немного двусмысленным. Часть «пользователь» буквально «пользователь» или что-то вроде «yourusername»? Если это "yourusername", это кажется мне излишним, поскольку вы делаете этот файл в своем домашнем каталоге. Изменить: похоже, что это буквально «пользователь»
fivedogit
8

Я использовал из cron "killall -0 programname || /etc/init.d/programname start". kill приведет к ошибке, если процесс не существует. Если он существует, он доставит процессу нулевой сигнал (который ядро ​​проигнорирует и не будет беспокоиться о передаче).

Эту идиому легко запомнить (ИМХО). Обычно я использую это, пока все еще пытаюсь выяснить, почему сама служба дает сбой. ИМХО программа не должна неожиданно исчезать :)


источник
7

Поместите свой запуск в цикл - поэтому, когда он завершится, он запустится снова ... while (true) {run my app ..}

Klathzazt
источник
4
Если сценарий умирает по неизвестным причинам, вполне вероятно, что он также отменит сценарий цикла, нет?
Гарет
4
Я с Гаратом, если это система, убивающая длительные процессы, то предложенный цикл, который начнется до приложения, будет убит первым.
ekerner
2
Чтобы ответить на два ваших комментария: Нет, если сценарий умирает по неизвестным причинам, тогда сценарий цикла не затрагивается, потому что он запускается в отдельном процессе, но да, если система случайным образом убивает длительные процессы, это все равно будет проблемой - однако я сомневаюсь, что это так. Об остальной части системы не сообщалось, что она затронута, и она заполнена другими долго выполняющимися процессами, которые также должны были быть перезапущены (упоминается только этот скрипт, имеющий проблему).
Klathzazt
4

По какой-то причине я не мог заставить работать решение Криса Вендта , и его было трудно отладить. Это почти то же самое, но легче отлаживать, исключает bash из сопоставления с образцом. Для отладки просто запустите: bash ./root/makerun-mysql.sh. В следующем примере с mysql-server просто замените значение переменных для processи makerunдля вашего процесса.

  • Создайте такой BASH-скрипт ( nano /root/makerun-mysql.sh):
#!/bin/bash
process="mysql"
makerun="/etc/init.d/mysql restart"
if ps ax | grep -v grep | grep -v bash | grep --quiet $process
then
    printf "Process '%s' is running.\n" "$process"
    exit
else
    printf "Starting process '%s' with command '%s'.\n" "$process" "$makerun"
    $makerun
fi
exit
  • Убедитесь, что он исполняемый, добавив соответствующие права доступа к файлу (т.е. chmod 700 /root/makerun-mysql.sh)

  • Затем добавьте это в свой crontab ( crontab -e):

# Keep processes running every 5 minutes
*/5 * * * * bash /root/makerun-mysql.sh
Cjohansson
источник
1
Обратите внимание: по сравнению с решением Криса Вендта скрипт здесь не запускается как фоновая задача.
Мейсон
2

superviseИнструмент от daemontoolsбы мое предпочтение - но тогда все пишет Дэн J Bernstein мои предпочтения :)

http://cr.yp.to/daemontools/supervise.html

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

Асфанд Кази
источник
1

Прежде всего, как запустить это приложение? Разветвляется на фон? Это запускается с nohup .. и тд? Если последнее, проверьте, почему он умер в nohup.out, если первый - ведение журнала сборки.

Что касается вашего основного вопроса: вы можете cron или запустить другой процесс в фоновом режиме (не лучший выбор) и использовать pidof в bashscript, достаточно просто:

if [ `pidof -s app` -eq 0 ]; then
    nohup app &
fi
gx.
источник
1

Вы можете сделать это службой, запускаемой из inittab (хотя некоторые Linux перешли на что-то более новое в /etc/event.d). Эти встроенные системы гарантируют, что ваша служба будет работать без написания собственных сценариев или установки чего-то нового.

Пол Томблин
источник
1

Это работа для DMD (демона мониторинга). их несколько; но я обычно просто пишу сценарий, который проверяет, запущен ли демон, и запускается, если нет, и помещаю его в cron для запуска каждую минуту.

Хавьер
источник
1

Check out », nannyна который есть ссылка в главе 9 (p197 или около того) « Unix Hater's Handbook » (один из нескольких источников книги в формате PDF).

Джонатан Леффлер
источник
1

Хороший и простой способ сделать это:

  1. Напишите свой сервер, чтобы он умер, если он не может прослушивать порт, который ожидает
  2. Установите cronjob, чтобы пытаться запускать ваш сервер каждую минуту

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

Кейси Родармор
источник
0

Я думаю, что лучшим решением будет, если вы тоже протестируете функцию. Например, если вам нужно было протестировать apache, недостаточно только проверить, существуют ли в системах процессы «apache».

Если вы хотите проверить, все ли в порядке с apache, попробуйте загрузить простую веб-страницу и проверьте, отображается ли ваш уникальный код на выходе.

Если нет, убейте apache с помощью -9, а затем выполните перезапуск. И отправьте письмо в корень (который является адресом для пересылки почты в корень компании / сервера / проекта).

Питер - Восстановить Монику
источник
1
Это правда. Многие решения для мониторинга, предложенные в других ответах, обеспечивают мониторинг протокола.
Оли
0

Это еще проще:

#!/bin/bash

export DISPLAY=:0

process=processname
makerun="/usr/bin/processname"

if ! pgrep $process > /dev/null
then
    $makerun &
fi

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

Радослав Ганчарек
источник
0

Установить минутный мониторинг cronjob можно так:

crontab -l> crontab; echo -e '* * * * * export DISPLAY = ": 0.0" && для приложения в "eiskaltdcpp-qt" "transfer-gtk" "nicotine"; do ps aux | grep -v grep | grep "$ app"; готово || "$ app" & '>> crontab; crontab crontab

Недостатком является то, что вводимые вами имена приложений должны быть найдены в ps aux|grep "appname"выводе и в то же время иметь возможность запускаться с этим именем:"appname" &

16851556
источник