Запустить скрипт bash в качестве демона

У меня есть скрипт, который запускает мой PHP-скрипт каждые X раз:

#!/bin/bash
while true; do
/usr/bin/php -f ./my-script.php
echo "Waiting..."
sleep 3
done

Как я могу запустить его как демон?


person Sergey B.    schedule 07.10.2013    source источник


Ответы (5)


Чтобы запустить его как полноценный демон из оболочки, вам нужно использовать setsid и перенаправить его вывод. Вы можете перенаправить вывод в файл журнала или /dev/null, чтобы отбросить его. Предполагая, что ваш скрипт называется myscript.sh, используйте следующую команду:

setsid myscript.sh >/dev/null 2>&1 < /dev/null &

Это полностью отсоединит процесс от вашей текущей оболочки (stdin, stdout и stderr). Если вы хотите сохранить выходные данные в файле журнала, замените первый /dev/null на ваш /path/to/logfile.

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

person micromoses    schedule 07.10.2013
comment
как тогда убить? - person Rho Phi; 18.08.2015
comment
Вам нужно будет найти его pid и отправить ему сигнал. Вот НЕБЕЗОПАСНЫЙ пример для Linux-систем: kill $(ps -fade | grep myscript.sh | grep -v grep | awk '{print $2}'). Это убьет все процессы, которые содержат myscript.sh в своем имени или параметрах, поэтому его не очень безопасно использовать, но вы можете настроить его в соответствии со своими потребностями. - person micromoses; 19.08.2015
comment
Спасибо, это полезно! Не могли бы вы объяснить, что делает 2>&1 < /dev/null? - person Daniel Patrick; 09.05.2016
comment
@DanielPatrick в bash (и большинстве других оболочек) это перенаправление stdin/stderr/stdout. > /dev/null (то же, что и 1>/dev/null) перенаправляет стандартный вывод (который является файловым дескриптором 1) на /dev/null. 2>&1 означает перенаправление всех stderr (файловый дескриптор 2) на файловый дескриптор 1, который уже перенаправлен на /dev/null. </dev/null прикрепляет /dev/null к стандартному вводу (fd 0). Все это позволяет сценарию отсоединиться от всех текущих источников ввода/вывода и повторно подключиться к /dev/null. Надеюсь, это ответы. - person micromoses; 09.05.2016
comment
Очень полезно, был знаком с перенаправлением, но не с файловыми дескрипторами. Спасибо! - person Daniel Patrick; 09.05.2016
comment
(в BASH) найдите его с помощью $ pgrep -l ‹ваше имя процесса› - person AAAfarmclub; 19.02.2017
comment
(в BASH) убейте его с помощью $ pkill ‹ваше имя процесса› - person AAAfarmclub; 19.02.2017
comment
Пока это единственный, который работает для меня! Большое Вам спасибо. - person Student; 15.08.2019

Демон — это просто программа, которая работает как фоновый процесс, а не находится под непосредственным контролем интерактивного пользователя...

[Приведенный ниже код bash предназначен для систем Debian — дистрибутивов Ubuntu, Linux Mint и т. д.]

Простой способ:

Простым способом было бы отредактировать файл /etc/rc.local, а затем просто запускать скрипт оттуда (т. е. каждый раз, когда вы загружаете систему):

sudo nano /etc/rc.local

Добавьте следующее и сохраните:

#For a BASH script
/bin/sh TheNameOfYourScript.sh > /dev/null &

Лучший способ сделать это — создать демона через Upstart:

sudo nano /etc/init/TheNameOfYourDaemon.conf

добавьте следующее:

description "My Daemon Job"
author "Your Name"
start on runlevel [2345]    

pre-start script
  echo "[`date`] My Daemon Starting" >> /var/log/TheNameOfYourDaemonJobLog.log
end script

exec /bin/sh TheNameOfYourScript.sh > /dev/null &

Сохранить это.

Подтвердите, что это выглядит нормально:

init-checkconf /etc/init/TheNameOfYourDaemon.conf

Теперь перезагрузите машину:

sudo reboot

Теперь, когда вы загружаете свою систему, вы можете увидеть файл журнала, в котором говорится, что ваш демон работает:

cat  /var/log/TheNameOfYourDaemonJobLog.log

Теперь вы можете запустить/остановить/перезапустить/получить статус своего демона через:

перезапустить: это остановит, затем запустит службу

sudo service TheNameOfYourDaemonrestart restart

start: запустит службу, если она не запущена

sudo service TheNameOfYourDaemonstart start

stop: остановит службу, если она запущена

sudo service TheNameOfYourDaemonstop stop

статус: отображает статус службы

sudo service TheNameOfYourDaemonstatus status
person CMP    schedule 04.08.2015
comment
Вы действительно должны указать дистрибутив, для которого это нужно, потому что эти команды и пути не являются правильными для всех дистрибутивов. - person SgtPooki; 07.10.2015
comment
Хороший вопрос, сержант Пуки. Я добавил предостережение, объясняющее, что мой пример относится к дистрибутивам Ubuntu / Mint и т. д. Спасибо за ваш комментарий. - person CMP; 14.05.2016
comment
Может ли кто-нибудь сделать дополнение systemd к этому ответу? :) - person Mitja; 18.12.2017
comment
Обратите внимание, что Upstart устарел. Ubuntu перешел на systemd. - person Pin; 11.05.2019

Вы можете перейти к /etc/init.d/ — вы увидите шаблон демона, называемый скелетом.

Вы можете продублировать его, а затем ввести свой сценарий под функцией запуска.

person Refael    schedule 07.10.2013
comment
вы также можете запустить скрипт в фоновом режиме, добавив «&» в конце или запустив его с nohup. - person LMC; 08.10.2013
comment
@LuisMuñoz, как я могу заставить его работать в фоновом режиме автоматически. например, когда вы вводите /etc/init.d/mysql start, демон запускается и работает в фоновом режиме по умолчанию. - person David Okwii; 01.04.2016
comment
@DavidOkwii поместите свой код в функцию и запустите ее в фоновом режиме. Проверьте мой ответ, добавленный к этому вопросу. - person LMC; 01.04.2016

Еще один крутой трюк — запускать функции или подоболочки в фоновом режиме, хотя это не всегда возможно.

name(){
  echo "Do something"
  sleep 1
}

# put a function in the background
name &
#Example taken from here
#https://bash.cyberciti.biz/guide/Putting_functions_in_background

Запуск подоболочки в фоновом режиме

(echo "started"; sleep 15; echo "stopped") &
person LMC    schedule 01.04.2016

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

  1. что такое демон инициализации (необязательно)
  2. что такое файл inittab (/etc/inittab)
  3. что делает файл inittab в вашем дистрибутиве (например, действительно ли он запускает все скрипты в /etc/init.d?)

Для вашей проблемы можно запустить скрипт на sysinit, добавив эту строку в /etc/inittab и заставить его возродиться в случае его завершения:

# start and respawn after termination
ttyS0::respawn:/bin/sh /path/to/my_script.sh

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

chmod +x /path/to/my_script.sh

Надеюсь это поможет

person Niko    schedule 31.01.2019