Иногда требуется не просто запустить программу, но и обеспечить ее работу, после перезагрузки, либо случайного падения. Можно в ручную следить за этим, но можно нужно, переложить эти заботы на откуп операционной системы. Для того чтобы сделать свою программу сервисом в Linux с использованием update-rc.d, достаточно выполнить следующее:

  • создать скрипт для управления жизненным циклом программы
  • назначить необходимые права на файл
  • зарегистрировать созданный скрипт как сервис
  • разрешить автозапуск сервиса

Как видим, шагов не так уж и много. И так начнем:

Создание скрипта

На первом шаге создадим файл в директории /etc/init.d/ с названием my-service

touch /etc/init.d/my-service

Шаблон скрипта выглядит следующим образом:

#!/bin/bash
#
### BEGIN INIT INFO
# Provides:             my-service
# Required-Start:       $syslog $remote_fs
# Required-Stop:        $syslog $remote_fs
# Should-Start:         $local_fs
# Should-Stop:          $local_fs
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    My Service
# Description:          My Service
### END INIT INFO
#
### BEGIN CHKCONFIG INFO
# chkconfig: 2345 55 25
# description: My Service
### END CHKCONFIG INFO
 
NAME="my-service"
APPLICATION_PATH="/opt/my-super-program"
PID_FILE="$APPLICATION_PATH/file.pid"
COMMAND="/usr/bin/python $APPLICATION_PATH/script.py 2>&1 > /dev/null & "


# запуск программы и запись её pid в файл 
start() {
    echo "Starting $NAME"
    eval $COMMAND
    PID=$(pgrep -f $NAME) 
    echo $PID >> $PID_FILE
    RETVAL=0
}

# остановка программы 
# получаем pid из файла и по нему принудительно завершаем процесс
stop() {
    if [ -f $PID_FILE ]; then
        echo "Shutting down $NAME"
        # отстреливаем процесс
        kill -9 $(cat $PID_FILE)
        rm -f $PID_FILE
        RETVAL=0
    else
        echo "$NAME is not running."
        RETVAL=0
    fi
}

# перезапуск 
# ничего сложного 
restart() {
    stop
    start
}

# проверка статуса, 
# если в списке процессов ос существует процесс, запущенный из директории нашей программы, то скорее всего, наша программа запущена, иначе нет.  
status() {
    echo `ps -ef` | grep -q "$APPLICATION_PATH"
    if [ "$?" -eq "0" ]; then
        echo "$NAME is running."
        RETVAL=0
    else
        echo "$NAME is not running."
        RETVAL=3
    fi
}

# команда выполняющая соответствие между полученным командами и приведенными выше функциями 
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status
        ;;
    restart)
        restart
        ;;
    *)
        echo "Usage: {start|stop|status|restart}"
        exit 1
        ;;
esac
exit $RETVAL

Данный шаблон предназначен для создания сервиса, запускающего скрипт из директории APPLICATION_PATH командой COMMAND. Для отслеживания состояния процесса потребуется так же PID_FILE, хранящий идентификатор запущенного процесса. Важно, чтобы программа, запускалась как демон и не выводила в консоль свои выходные данные, нужно после вызова дописать 2>&1 > /dev/null &

Из шаблона можно так же понять, что скрипт состоит из нескольких частей:

  • заголовок комментариев, со служебной информацией. Там, например указывается, от каких сервисов зависит данный сервис при старте/остановке, описание/название сервиса и тд.
  • главный case, обрабатывающий полученные скриптом команды.
  • функции реализующие команды: запуска, остановки, проверки статуса и тд.

Назначение прав

Здесь все просто, чтобы скрипт смог выполняться, нужно дать необходимые права для данного файла. Это делается следующей командой:

chmod +x /etc/init.d/my-service 

Регистрация скрипта как сервиса

Чтобы операционная система узнала о существовании нашего сервиса, потребуется его зарегистрировать. Для этого выполним команду:

update-rc.d my-service defaults

Разрешить автозагрузку

Теперь наш сервис известен операционной системе, и с ним уже можно работать, например, запускать или останавливать:

service my-service start

Но, по умолчанию, после перезагрузки операционной системы, наша программа не будет работать. Для включения автозагрузки сервиса потребуется вызвать update-rc.d со следующими параметрами:

update-rc.d my-service enable

После этого, наш сервис полностью готов к работе 😉