Как автоматически перезапустить фоновый процесс Linux, если он не работает?

32

У меня есть процесс, который выполняется сценарием init.d на фоне. Например:

case "$1" in 
    start)
       /bin/myprocess &
    stop)
       killall myprocess
    restart)
       killall myprocess
       /bin/myprocess &
esac

В определенных условиях myprocess может завершиться с ошибкой и вернуться. Есть ли (стандартный) способ, как обнаружить его сбой и автоматически перезапустить?

Хонза
источник
Конечно, но это зависит от распределения. Практически все они предоставляют своего рода менеджера по обслуживанию.
Дэвид Шварц
Стандартного дистрибутива нет, но есть buildroot. Так что я должен сделать это вручную ...
Honza

Ответы:

14

Самый простой способ - добавить его в / etc / inittab , который предназначен для таких вещей:

respawn Если процесс не существует, запустите процесс. Не ждите его завершения (продолжите сканирование файла / etc / inittab). Перезапустите процесс, когда он умрет. Если процесс существует, ничего не делайте и продолжайте сканирование файла / etc / inittab.

Например, вы можете сделать это:

# Run my stuff
myprocess:2345:respawn:/bin/myprocess
Алан Шутко
источник
Обратите внимание, что /etc/inittabработает (или даже существует), если и только если у вас есть система инициализации на основе sysvinit. С upstart и с systemd это не так. Вы должны установить либо busybox (очень примитивная оболочка, делающая sysadm восстанавливающим задачи болезненным, но он может заменить sysvinit-совместимый initd), либо sysvinit (это ископаемое). В докерном контейнере только первое не больно.
Петер говорит восстановить Монику
27

У Buildroot есть три возможных системы инициализации, поэтому есть три способа сделать это:

BusyBox init

При этом каждый добавляет запись в /etc/inittab.

::respawn:/bin/myprocess

Обратите внимание, что BusyBox initимеет уникальный /etc/inittabформат. Второе поле не имеет смысла, а первое поле - это не идентификатор, а базовое имя устройства.

Linux "Система V" init

Снова, каждый добавляет запись к /etc/inittab.

myprocess:2345:respawn:/bin/myprocess

systemd

Один пишет файл модуля, скажем, в /etc/systemd/system/myprocess.service:

[Unit]
Description=My Process

[Service]
ExecStart=/bin/myprocess
Restart=always

[Install]
WantedBy=multi-user.target

Включите это для автоматического запуска при загрузке с:

systemctl enable myprocess.service

Запустите его вручную с помощью:

systemctl start myprocess.service

дальнейшее чтение

JdeBP
источник
но когда вы используете этот подход inittab, тогда ваш процесс больше не доступен через интерфейс службы? то есть ты не можешь идти service mything startили service mything stopбольше .... есть ли способ получить лучшее из обоих? то есть нерасширяемый сервис sysvinit, но можно ли его использовать и через «сервис»?
скакун
25

Как насчет создания подоболочки с циклом, который постоянно вызывает один и тот же процесс?

Если он заканчивается, следующая итерация цикла продолжается и запускается снова.

(while true; do 
    /bin/myprocess
done) &

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

Следующим шагом будет интересно, что произойдет, если cron умрет, но в какой-то момент вы должны чувствовать себя в безопасности и перестать беспокоиться

Trylks
источник
3

Вы могли бы использовать Monit . Это действительно простой в использовании и довольно гибкий. Посмотрите, например, эту конфигурацию для перезапуска процесса Tomcat при сбое.

check process tomcat with pidfile /var/run/tomcat.pid
   start program = "/etc/init.d/tomcat start"
   stop  program = "/etc/init.d/tomcat stop"
   if failed port 8080 type tcp then restart

У этого также есть много примеров конфигурации для многих случаев использования.

Клайд д'Круз
источник
1

Если вы не являетесь суперпользователем или пользователем root, и если в вашей системе Linux установлен Docker, вы можете создать образ докера вашего процесса, используя docker для перезапуска вашего процесса, если система перезагружается.

Файл: docker-compose.yml

version: "3"
services:
  lserver:
    image: your_docker_image:latest
    ports:
    - 8080:8080   # just use 8080 as an example
    restart: always  # this is where your process can be guaranteed to restart

Чтобы запустить ваш докер-контейнер,

docker-compose up -d

Я считаю, что легко справиться с собственным процессом с помощью автоматического перезапуска, если я не являюсь суперпользователем системы.

Для примера примера того, как создать образ докера, вот быстрый пример:

Файл: Dockerfile

FROM alpine:3.5

RUN apk update && apk upgrade && rm -rf /var/cache/apk/*
WORKDIR /app
COPY my-process-server /app
RUN ln -s /app/my-process-server /usr/local/bin/my-process-server

EXPOSE 8080

CMD ["my-process-server"]
Майкл Цинь
источник
0

В моем случае, как быстрое исправление, я изменил и использовал решение @Trylks, чтобы обернуть программу, которую я запускал. Я хотел, чтобы это закончилось только на чистом выходе.

Должен работать в большинстве снарядов:

#!/bin/sh

echo ""
echo "Use: $0 ./program"
echo ""

#eg="/usr/bin/apt update"

echo "Executing $1 ..."

EXIT_CODE=1
(while [ $EXIT_CODE -gt 0 ]; do
    $1
    # loops on error code: greater-than 0
    EXIT_CODE=$?
done) &
user9869932
источник
0

Вы можете использовать рестартер

start)
   restarter -c /bin/myprocess &
stop)
   pkill -f myprocess

На более новых системах используйте systemd, который решает все эти тривиальные проблемы

sivann
источник