28

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

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

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

7 ответов7

24

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

BusyBox init

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

::respawn:/bin/myprocess

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

Linux "System 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

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

20

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

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

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

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

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

14

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

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

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

# Run my stuff
myprocess:2345:respawn:/bin/myprocess
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

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

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

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

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) &

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