Як автоматично перезапустити фоновий процес Linux, якщо він не працює?


32

У мене процес, який виконується скриптом init.d на задньому плані. Наприклад:

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

За певних умов мій процес може вийти з ладу і повернутися. Чи є якийсь (стандартний) спосіб, як виявити його збій і перезапустити автоматично?


Звичайно, але це залежить від розподілу. Насправді всі вони надають якогось сервісного менеджера.
Девід Шварц

Існує не стандартний розподіл, а вбудований. Тож я маю це робити вручну ...
Honza

Відповіді:


14

Найпростішим способом було б додати його до / etc / inittab , який призначений для подібних дій:

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

Наприклад, ви можете це зробити:

# Run my stuff
myprocess:2345:respawn:/bin/myprocess

Зауважте, /etc/inittabпрацює (або навіть існує) тоді і тільки тоді, якщо у вас є система init на основі sysvinit. З початком роботи та з systemd - це не так. Вам потрібно встановити або busbox (дуже примітивна оболонка, яка робить завдання відновлення системи sysadm болісними, але вона може замінити initd, сумісний із sysvinit), або sysvinit (це викопний матеріал). У докерній ємності лише перше не боляче.
Peterh каже відновити Моніку

27

Buildroot має три можливі системи init, тож це три способи:

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

Подальше читання


але коли ви використовуєте цей підхід inittab, то ваш процес вже не доступний через інтерфейс 'service'? тобто ви не можете піти service mything startчи service mything stopбільше .... чи є спосіб зробити найкраще з обох? тобто нерозбірний сервіс sysvinit, але чи можна використовувати його через "сервіс"?
horseyguy

25

А як же створити нижню частину корпусу з циклом, який викликає постійно один і той же процес?

Якщо вона закінчиться, наступна ітерація циклу продовжується і запускається знову.

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

Якщо нижня частина корпусу відмирає, все-таки закінчилося. Єдиною можливістю в такому випадку було б створити інший процес (я буду називати його некромантом), який перевіряє, чи живий ваш процес, запустити його, якщо його немає, і запустити цього некроманта з кроном, щоб ви могли регулярно перевіряти це.

Наступним кроком буде цікаво, що може статися, якщо крон помер, але в якийсь момент ви повинні почувати себе в безпеці і перестати турбуватися.


3

Ви можете скористатися Монітом . Це дійсно проста у використанні та досить гнучка. Дивіться, наприклад, цю конфігурацію для перезапуску процесу 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

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

Для прикладу, як створити зображення докера, ось короткий приклад:

Файл: Докерфайл

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

0

Ви можете використовувати перезапуск

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

У нових системах використовують systemd, який вирішує всі ці тривіальні проблеми

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.