Вы здесь

Запуск bash скрипта в фоновом режиме через Systemd

Systemd

Понадобилось на днях написать простой bash-скрипт, для постоянного мониторинга каталога на наличие в нем файлов *.pdf, с последующей их конвертацией в формат txt. Скрипт должен был работать в фоновом режиме и автоматически запускаться при перезагрузке.

Для реализации работы в фоне сначала написал Linux - демон на C, но потом решил что для моей задачи это слишком, и реализовал это при помощи Systemd.

Для начала нужно убедиться, что ваш дистрибутив работает с Systemd, командой:

readlink /proc/1/exe
если вывод будет /sbin/init - то у вас используется SysV, и вам нужно либо обновить дистрибутив, как в моем случае, я обновил Debian 7 Wheezy до Debian 8 Jessie, либо реализовать работу в фоновом режиме другим способом.

Если вывод такой:
/lib/systemd/systemd - то все в порядке, у вас Systemd.

Systemd осуществляет свою работу с помощью так называемых юнитов systemd.
Юнит (Unit) - это конфигурационный файл, расположенный в одной из директорий:

/run/systemd/system/ — юниты, созданные в рантайме. Этот каталог приоритетнее каталога с установленными юнитами из пакетов.
/etc/systemd/system/ — юниты, созданные и управляемые системным администратором. Этот каталог приоритетнее каталога юнитов, созданных в рантайме. В этом каталоге мы и будем создавать свой юнит.

Переходим в каталог /etc/systemd/system/ и создаем в нем, либо копируем какой-либо существующий файл, к примеру sshd.service, и в нем пишем:

  1. [Unit]
  2. Description=MyBashScript
  3. After=syslog.target
  4.  
  5. [Service]
  6.  
  7. ExecStart=/bin/bash '/home/user/scripts/script.sh'
  8. Type=forking
  9.  
  10. [Install]
  11. WantedBy=multi-user.target
  12. Alias=bash.service

Подробнее о каждой секции:
Секция [Unit]:
Содержит общую информацию о сервисе, его описание, и то, что он должен стартовать после запущенного демона Syslog.

Секция [Service]
Непосредственная информация о нашем сервисе.
Параметр ExecStart указывает на исполняемый файл нашего сервиса. Нужно указывать абсолютные пути, в случае с bash-скриптом путь до скрипта берем в одинарные кавычки.
Type=forking означает, что запускаемый скрипт будет работать в режиме демона. Если мы хотим, чтобы скрипт выполнился один раз, то указываем Type=simple.

Секция [Install]
Последняя секция [Install] содержит информацию о цели, в которой сервис должен стартовать. В данном случае мы хотим, что сервис должен быть запущен, когда будет активирована цель multi–user.target (это аналог init 3 в SysV).
Alias=bash.service - для удобства создадим алиас, чтобы проще управлять нашим сервисом через systemctl.

Это работающий файл сервиcа Systemd, с небольшим функционалом. Сохраняем файл, и выполняем команду systemctl daemon-reload, чтобы Systemd узнал о нашем сервисе, и вы могли его запустить командой systemctl start bash.service.
У меня запустить получилось не с первого раза, так как сначала я указал не абсолютный путь в параметре ExecStart секции [Service]. После исправления Systemd все равно ругался на ту же ошибку, помогла перезагрузка.

Для просмотра состояния, старта, остановки, перезагрузки, включения или выключения системных сервисов используется команда systemctl. В более ранних версиях Systemd использовались команды service и chkconfig, они по прежнему включены в систему, в основном для обратной совместимости.

Ниже представлены основные команды systemctl:

systemctl start name.service – запуск сервиса.
systemctl stop name.service — остановка сервиса
systemctl restart name.service — перезапуск сервиса
systemctl try-restart name.service — перезапуск сервиса только, если он запущен
systemctl reload name.service — перезагрузка конфигурации сервиса
systemctl status name.service — проверка, запущен ли сервис с детальным выводом состояния сервиса
systemctl is-active name.service — проверка, запущен ли сервис с простым ответом: active или inactive
systemctl list-units --type service --all – отображение статуса всех сервисов
systemctl enable name.service – активирует сервис (позволяет стартовать во время запуска системы)
systemctl disable name.service – деактивирует сервис
systemctl reenable name.service – деактивирует сервис и сразу активирует его
systemctl is–enabled name.service – проверяет, активирован ли сервис
systemctl list-unit-files --type service – отображает все сервисы и проверяет, какие из них активированы
systemctl mask name.service – заменяет файл сервиса симлинком на /dev/null, делая юнит недоступным для systemd
systemctl unmask name.service – возвращает файл сервиса, делая юнит доступным для systemd

Для более подробного знакомства с Systemd рекомендую почитать:

Шпаргалка по управлению сервисами CentOS 7 с systemd
Официальная документация по Systemd, переведенная на русский

Также рекомендуем