Как написать systemd unit файл для автозагрузки

Обновлено: 04.07.2024

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

Юниты systemd и их разновидности.

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

В контексте systemd юниты — это отдельные объекты, которыми управляет эта система. Как и игровые войска, они имеют свои разновидности, у каждой из которых есть свое предназначение. Если вы читали предыдущие статьи, то знаете как минимум одну разновидность таких объектов — сервисы. Вот некоторые другие виды юнитов, о которых я, возможно, расскажу в следующих статьях:

  • точки монтирования,
  • таймеры,
  • таргеты или цели,
  • устройства.

Основными директориями для хранения юнитов в Ubuntu 16.04 являются:

  • /lib/systemd/system — здесь находятся юниты, созданые автоматически при установке пакетов;
  • /etc/systemd/system — пользовательские, вернее, администраторские юниты.

Юниты systemd и их разновидности

Скриншот выше демонстрирует содержимое директории с файлами юнитов.

Файлы юнитов содержат разделы с набором параметров и их значений, разделенных знаком «=». Слева название параметра, справа значение, все предельно просто. Для начала создадим файл с названием my_backup.service и поместим его в /etc/systemd/system. Впишем в него следующие строки:

Идея этого решения принадлежит человеку с ником mezcalero из IRC чата systemd.

Давайте разберем представленный выше код.

Раздел [Unit] хранит общие сведения о юните. В данном случае он содержит только описание (Description).

Раздел [Service] объединяет сведения, необходимые для выполнения юнитом его задач. Type определяет тип сервиса (не путайте его с разновидностями юнитов), oneshot означает, что сервис должен выполнить разовую задачу и завершиться. ExecStop указывает скрипт, который должен быть выполнен перед остановкой сервиса. Есть еще ExecStart, этот параметр используется чаще и определяет команду, которая должна быть выполнена сразу после запуска сервиса. RemainAfterExit=true предписывает systemd считать процесс активным после его завершения.

Секция [Install] содержит сведения о том, при каких обстоятельствах должен быть запущен сервис. WantedBy=multi-user.target устанавливает запуск при обычной загрузке компьютера.

Но это еще не все. Скрипт, который мы указали в качестве значения ExecStop, на данный момент не существует.

Приведенный выше код нужно поместить в файл /usr/local/bin/my_backup, а затем сделать его исполняемым:

Хотя наш скрипт совсем простой, давайте все же разберем его. Первая строка — обязательное начало любого bash скрипта. Вторая получает текущую дату и время в определенном нами формате и помещает ее в переменную current_date. Третья запускает архиватор и сообщает ему, что и куда архивировать. Кстати, не забудьте подставить свои пути вместо русского текста.

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

Создаем Unit

Обратите внимание: в команде выше я использовал mybackup, а не mybackup.service, хотя подразумевал именно это. Дело в том, что если тип юнита не указан, предполагается, что это .serivice. Полный вариант сработал бы точно так же.

Перезагрузите компьютер и проверьте, появился ли архив в указанном месте.

По желанию можно настроить сохранение резервных копий вне локального компьютера, например, в облачном хранилище. В этом случае может потребоваться проверка подключения к сети и доступности самого хранилища. Можно также настроить создание резервных копий не перед выключением, а по расписанию с помощью юнита timer. Возможно, в следующих статьях я продолжу эту тему и покажу, как это можно сделать, а заодно — продемонстрирую работу юнитов других типов.

Далеко не всегда нужно писать собственный скрипт при создании сервиса systemd. Зачастую сервисные файлы пишутся с целью управления уже существующими программами, путь к которым определяется параметрами ExecStart или ExecStop. Наш скрипт тоже использует существующую программу — tar. По большому счету, можно было обойтись и вовсе без него, сразу прописав все необходимые параметры в сервисном файле. Я включил его создание в статью только с целью демонстрации самой возможности. Но пользовательский скрипт все же будет полезен, если вы захотите усложнить задачу: отослать уведомление на электронную почту, удалить самый старый из архивов и т. д.

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

Создаем Unit

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


Что дадут вам Systemd юниты?

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

Некоторые функции, которые легко реализовать:

  • Активация на основе сокетов: Сокеты, связанные с сервисом, лучше всего вырываются из самого демона, чтобы обрабатываться отдельно. Это дает ряд преимуществ,- например, задержка запуска службы до тех пор, пока соответствующий сокет не будет доступен. Это также позволяет системе создавать все сокеты до начала запуска процесса, что позволяет параллельно загружать связанные службы.
  • Активация на основе шины: Unit-ы также могут быть активированы на интерфейсе шины, предоставляемом D-Bus-ом. Устройство может быть запущено когда соответствующая шина доступна.
  • Активация на основе пути: Unit может быть запущен на основе активности или наличия определенных путей к файловой системе. Это использует inotify.
  • Активация на основе устройства: Unit-ы также могут быть запущены при первой доступности (подключении) связанного оборудования за счет использования событий udev.
  • Неявное сопоставление зависимостей: Большая часть структуры зависимостей для юнитов может быть построена самой системой. Вы все равно можете добавить информацию о зависимостях, но большая часть тяжелой работы будет решена за вас.
  • Экземпляры и шаблоны: Файлы блока шаблонов могут использоваться для создания нескольких экземпляров одного и того же общего устройства. Это позволяет создавать небольшие вариации или единичные unit-ы, которые обеспечивают одну и ту же общую функцию.
  • Простое упрощение безопасности: Юниты могут реализовать некоторые довольно хорошие функции безопасности, добавив простые директивы. Например, вы можете указать какой доступ можно использовать ( чтение, запись) при работе с файловой системой, ограничить возможности ядра, установить приватный /tmp фолдер и сетевой доступ.
  • Drop-ins и snippets: Units можно легко расширить, предоставив фрагменты, которые будут отменять части файла системы. Это позволяет легко переключаться между vanilla и индивидуальными реализациями.

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

Как я могу найти/ Где находятся Systemd Unit в Unix/Linux?

Файлы, определяющие, как systemd будет обрабатывать unit, можно найти в разных местах, каждое из которых имеет разные приоритеты и смысл.

Все копии системных файлов системы (я имею ввиду всех юнитов) можно найти в /lib/systemd/system каталоге. Файлы, хранящиеся здесь, могут быть запущены и остановлены по требованию, но во время сеанса. Это будет общий файл ванильной единицы, который часто записывается сторонними разработчиками проекта, которые должны работать в любой системе, которая развертывает systemd в своей стандартной реализации. Вы не должны редактировать файлы в этом каталоге. Вместо этого вы должны переопределить файл (если необходимо) используя другое расположение файла, которое заменит файл в этом месте.

Если вы хотите переопределить только определенные директивы из системных unit файлов, вы можете фактически предоставить фрагменты unit файла в подкаталоге. Они будут добавлять или изменять директивами копии системы, позволяя указать только параметры, которые вы хотите изменить.

Также есть место для определения run-time unit-ов в /run/systemd/system. Файлы, найденные в этом каталоге, имеют приоритет между /etc/systemd/system и/lib/systemd/system.

Файлы в этом месте дают меньший приоритет, чем прежнее местоположение, но больший приоритет, чем последнее. Сам процесс systemd использует это местоположение для динамически создаваемых unit файлов, созданных во время выполнения. Этот каталог можно использовать для изменения поведения устройства системы в течение всего сеанса. Все изменения, внесенные в этот каталог, будут потеряны при перезагрузке сервера.

Типы systemd Unit файлов

Как вы можете видеть, существует множество различных юнитов с которыми взаимодействует система. Многие из них работают вместе, чтобы добавить функциональности. В основном, используется .service из-за их полезности.

Структура systemd Unit файлов

Внутренняя структура файлов организована с помощью разделов. Разделы обозначаются двумя квадратными скобками «[» и «]» с именем раздела, заключенного внутри. Каждый раздел продолжается до начала следующего раздела или до конца файла.

Названия разделов хорошо определены и учитывают регистр. Таким образом, раздел [Unit] не будет интерпретироваться правильно, если он записан как [UNIT]. Если вам нужно добавить нестандартные разделы для анализа (отличными от systemd), вы можете добавить X-префикс к имени раздела.

В этих разделах поведение устройства и метаданные определяются с помощью простых директив с использованием формата ключа-значения с назначением, обозначенным знаком равенства, например:

В случае переопределения файла (например, содержащегося в каталоге unit.type.d) директивы могут быть сброшены путем назначения пустой строкой. Например, копия единичного файла системы может содержать директиву, заданную таким образом:

Значение default_value можно исключить в файле переопределения, указав Directive1 (без значения), например:

Сейчас рассмотрим каждый из юнитов по отдельности.

Хотя порядок разделов не имеет значения для systemd при парсинге файла, этот раздел часто размещается сверху, потому что он предоставляет обзор устройства. Некоторые общие директивы, которые вы найдете в разделе [Unit]:

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

[Install]

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

[Service]

Раздел [Service] используется для предоставления конфигурации, которая применима только для служб. Одной из основных вещей, которые должны быть указаны в разделе [Service], является Type= служба. Это классифицирует услуги по их процессу и демонизирующему поведению. Это важно, потому что он сообщает systemd, как правильно управлять службой и узнать его состояние.

Директива Type= может быть одной из следующих:

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

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

  • ExecStart=: Нужно указать полный путь и аргументы команды, которая должна быть выполнена для запуска процесса. Это может быть указано только один раз (кроме сервисов «onehot»). Если для пути к команде предшествует символ «-» тире, будут приняты ненулевые статусы выхода без маркировки активации устройства как сбой.
  • ExecStartPre=:Нужно указать полный путь и аргументы команды, которые должны быть выполнены до запуска основного процесса. Это можно использовать несколько раз.
  • ExecStartPost=: Это имеет те же самые качества, что и ExecStartPre = за исключением того, что данная дириктива указывает команды, которые будут запускаться после запуска основного процесса.
  • ExecReload=: Эта необязательная директива указывает команду, необходимую для перезагрузки конфигурации службы, если она доступна.
  • ExecStop=: Это указывает на команду, необходимую для остановки службы. Если это не указано, процесс будет немедленно уничтожен, когда служба будет остановлена.
  • ExecStopPost=: Это можно использовать для указания команд для выполнения после остановке команды.
  • RestartSec=: Если автоматический перезапуск службы включен, это указывает время ожидания перед попыткой перезапуска службы.
  • Restart=: Это указывает на обстоятельства, при которых systemd будет пытаться автоматически перезапустить службу. Она может быть установлена как значения «always», «on-success», «on-failure», «on-abnormal», «on-abort» или «on-watchdog». Это приведет к перезапуску в соответствии с тем, как служба была остановлена.
  • TimeoutSec=: Это устанавливает время, в течение которого система будет ждать остановки службы, прежде чем пометить ее как неудачную или убитую принудительно. Вы можете установить отдельные таймауты с помощью TimeoutStartSec = и TimeoutStopSec =.

[Socket]

Socket очень часто встречаются в конфигурациях systemd, потому что многие службы реализуют активацию на основе сокетов, чтобы обеспечить лучшую распараллеливание и гибкость. Каждый блок socket-а должен иметь соответствующий сервисный модуль, который будет активирован, когда сокет получает активность.

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

Чтобы указать фактический сокет, эти директивы являются общими:

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

Другие характеристики сокетов можно контролировать с помощью дополнительных директив:

  • Accept=: Это определяет, будет ли запущен дополнительный экземпляр службы для каждого соединения. Если установлено значение false (по умолчанию), один экземпляр будет обрабатывать все соединения.
  • SocketUser=: С помощью Unix-сокета задается его владелец. Если не указать, то будет пользователь root.
  • SocketGroup=: С помощью Unix-сокета задается владелец группы. Это будет root группа, если не указано ни то, ни другое. Если установлен только SocketUser =, systemd попытается найти подходящую группу.
  • SocketMode=: Для сокетов Unix или буферов FIFO это устанавливает разрешения для созданного объекта.
  • Service=: Если имя службы не совпадает с именем .socket, эта служба может быть указана с помощью этой директивы.

[Mount]

Модули монтирования позволяют управлять точкой монтирования изнутри systemd. Точки монтирования называются в соответствии с управляемым им каталогом с применением алгоритма перевода.

Mount юниты часто переводятся непосредственно из файла /etc/fstab во время процесса загрузки. Для автоматически созданных определений единиц и те, которые вы хотите определить в единичном файле:

  • What=: Абсолютный путь к ресурсу, который необходимо смонтировать.
  • Where=: Абсолютный путь точки монтирования, в которой должен быть установлен ресурс. Это должно быть таким же, как имя файла устройства, за исключением использования стандартной записи файловой системы.
  • Type=: Тип файловой системы для монтирования.
  • Options=: Любые параметры монтирования, которые необходимо применить. Это список, разделенный запятыми.
  • SloppyOptions=: Логическое значение (0 или 1), которое определяет произойдет ли сбой монтирования, если есть параметр непризнанного монтирования.
  • DirectoryMode=: Если родительские каталоги необходимо создать для точки монтирования, это определяет режим разрешений этих папок.
  • TimeoutSec=: Настраивает время, в течение которого система будет ждать, пока операция монтирования не будет отмечена как сбой.

[Automount]

Этот модуль позволяет автоматически устанавливать подключенный модуль .mount при загрузке. Как и в случае с модулем .mount, эти юниты должны быть названы в честь пути переведенной точки монтирования.

[Automount] Раздел довольно прост, разрешены только следующие два варианта:

  • Where=: Абсолютный путь automount в файловой системе. Это будет соответствовать имени файла, за исключением того, что вместо перевода используется условное обозначение пути.
  • DirectoryMode=:Если необходимо создать automount или любые родительские каталоги, это определит настройки разрешений для этих компонентов пути.

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

Как и mount параметры, блоки swap могут быть автоматически созданы из /etc/fstab или могут быть сконфигурированы через выделенный unit файл.

Раздел [Swap] может содержать следующие директивы для конфигурации:

  • What=: Абсолютный путь к местоположению подкачки (будь то файл или устройство).
  • Priority=: Данная опция принимает целое число, которое задает приоритет для настройки подкачки.
  • Options=: Любые параметры, которые обычно задаются в файле /etc/fstab, могут быть установлены с помощью этой директивы. Используется список, разделенный запятыми.
  • TimeoutSec=: Данная опция задает временя, в течение которого, система ожидает активацию своп-а, прежде чем отмечать операцию как зафейленую.

Блок path, определяет путь файловой системы, который systmed может отслеживать изменения. Должен существовать другой блок, который будет активирован, когда определенная активность будет обнаружена в местоположении пути. Активность пути определяется тем, что он не влияет на события.

Раздел [Path] может содержать следующие директивы:

  • PathExists=: Эта директива используется для проверки того, существует ли этот путь. Если путь существует, активируется соответствующий блок.
  • PathExistsGlob=: Данная опция такая как и выше, но поддерживает глобальные выражения для определения существования пути.
  • PathChanged=: Данную опцию используют для отслеживания изменений местоположение пути. Связанный блок активируется, если обнаружено изменение (проверяется когда файл закрыт).
  • PathModified=: Данная опция такая как и выше, но активируется при записи файлов, а также когда файл закрыт.
  • DirectoryNotEmpty=: Эта директива позволяет systemd активировать связанный блок, когда каталог больше не пустой.
  • Unit=: Это указывает, что устройство активируется, когда условия пути, указанные выше, выполняются. Если это будет опущено, systemd будет искать файл .service, который имеет то же имя базового юнита, что и этот блок.
  • MakeDirectory=: Данная директива определяет, будет ли systemd создавать структуру каталогов перед просмотром.
  • DirectoryMode=: Если вышеуказанная директива включена, то данная опция установит режим разрешения любых компонентов пути, которые должны быть созданы.

[Timer]

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

Раздел [Timer] может содержать некоторые из следующих директив:

[Slice]

Раздел [Slice] на самом деле, не имеет .slice специфической конфигурации. Вместо этого он может содержать некоторые директивы управления ресурсами, которые перечислялись выше.

Хватит теории, перейдем к практике.

Пишем systemd Unit файл

PS: Вот небольшая статья:

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

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

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

Ниже приведены некоторые из наиболее распространенных спецификаторов, которые будут заменены, когда юнит-экземпляра интерпретируется с соответствующей информацией:

Используя приведенные выше идентификаторы в шаблоне файла, Systemd заполнит правильные значения при интерпретации шаблона для создания юнит-экземпляра.

Примеры systemd Unit файлов

И записываем в него следующий код:

Добавим томкат в автозагрузку ОС:

Чтобы проверить статус, выполняем:

Как видим, все четко работает. На этом, у меня все! Больше примеров будет дальше. Я буду добавлять их по мере необходимости. Но в основном, я использую шаблон что выше ( только немного его видоизменяю).

10 thoughts on “ Пишем systemd Unit файл ”

Вроде даже в книгах читал по модули systemd, но тут очень хорошо так на пальцах всё показано, для дальнейшего понимания очень полезно. Спасибо!

Можно ли как-то указать куда писать лог-файл. Есть python программа, unit к ней оформил, всё работает, только вот лог она пишет в файл syslog, а нужно в другой в /var/log/python.log например.

Да, можно. Нужно прописать в [Service] секции, следующии строки:

На форуме капча не работает зарегистрироваться нельзя так что пишу сюда.

Пытаюсь оформить сервис для vmpsd. Не запускается.
Если добавить:
StandardOutput=
StandardError=

То получаю:
Failed to parse output specifier, ignoring:

Что-то не так делаешь, нужно привести к следующему виду:

[Service]
Type=forking
StandardOutput=/var/StandardOutput.log
StandardError=/var/StandardError.log

У меня такая же ошибка как у vasyun. Type=idle, если сделать forking, то вообще юнит не запускается, приходиться жать Ctrl-C.

Спасибо Автор! Ваш труд оказался полезным! Всех благ Вам!

Добрый день!
Можете объяснить точный функционал опции After?
Она несет только информацию для пользователя, что именно он должен запустить перед запуском текущего юнита?
Или все что там прописано автоматически запускается при запуске текущего юнита?

Первое и не просто для пользователя, а для правильной последовательности запуска того юнита, где встречается after и в данном случае не перед, а после.

Взято с другого сайта:
Запускать юнит после какого-либо сервиса или группы сервисов (например network.target):
After=network.target

Добавить комментарий Отменить ответ

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

date

21.04.2020

directory

CentOS, Linux

comments

комментариев 8

В данной статье мы рассмотрим основы управлением автозагрузкой сервисов и скриптов в Linux CentOS 7/8. В частности, разберем основы работы с демоном systemd, научимся добавлять в автозагрузку сервисы и убирать их оттуда, а также рассмотрим альтернативные варианты запуска скриптов или демонов после старта системы.

Задача статьи – научить вас быстро разобраться со списками служб и скриптов которые запускаются в Linux автоматически, добавить в автозагрузку свои службы или скрипты, или отключить автозапуск определённых программ.

Systemd: управление автозагрузкой служб в Linux

В большистве популярных современных популярных дистрибутивов Linux (CentOS 7, RHEL, Debian, Fedora и Ubuntu) в качестве демона автозагрузки вместо init.d используется systemd. Systemd – менеджер системы и служб Linux, используется для запуска других демонов и управления ими в процессе работы, использует unit-файлы из /etc/systemd/system (init.d использовал скрипты из каталога /etc/init.d/). Systemd позволяет распараллелить запуск служб в процессе загрузки ОС, тем самым ускоряя запуск.

Для управления system используется команда systemctl.

Для начала, после загрузки системы, мы проверим список юнитов, которые в данный момент добавлены в systemd:

systemctl list-units

Список unit-файлов можно получить командой:

Данная команда отобразит все доступные юнит-файлы (не зависимо от того, были они загружены в systemd после загрузки ОС или нет).

Чтобы вывести список активных сервисов и их состояние, выполните:

Как видим из списка, здесь отображаются даже сервисы, которые не были найдены на диске «not-found».

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

systemctl list-units —type=service вывести список сервисов в centos

Добавление сервиса в systemd

Для управления сервисами в systemd используется особый синтаксис. После имени серверсв в конце нужно указывать .service. Например:

systemctl enable nginx.service – команда добавит в автозагрузку веб-сервер nginx

Данная команда создаст символическую ссылку на копию файла, указанного в команде сервиса, в директории автозапуска systemd.

Вывод этой команды показывает в какой директории был создан симлинк на файл сервиса.

Чтобы посмотреть добавлен тот или иной сервис в автозагрузку, можно проверить его статус:

systemctl status nginx.service

При выводе нужно обратить внимание на строку:

Значение enabled означает что данный сервис загружается автоматически (добавлен в автозагрузку). Если сервис не загружается автоматом, здесь буде указано disabled.

Удаление сервиса из systemd

Вы можете удалить сервис из автозагрузки, чтобы он не запускался после старта Linux (при этом сам сервис с сервера не удаляется). Чтобы удалить сервис из автозагрузки, выполните команду:

systemctl disable нужный_сервис

Например, чтобы удалить из автозагрузки nginx, выполните:

После выполнения команды, симлинк на файл сервиса будет удален из директории systemd. Можно проверить, есть ли юнит в автозагрузке:

Systemd: маскировка юнитов

В моей практике встречались «вредные» сервисы, которые после удаления их из автозагрузки, все равно там оставались и запускались после рестарта ОС. Чтобы решить этот вопрос, можно замаскировать сервис:

systemctl mask nginx.service

И после этого, он вообще не будет запускаться, ни вручную, ни после перезагрузки ОС:

Снять маску можно командой:

Если после маскировки сервиса, вы проверите юнит-файлы, то увидите, что сервис помечен как замаскированный (состояние masked):

systemctl mask маскировка сервиса

Таким нехитрым способом, можно избавить себя от удаления сервиса, даже если он не удаляется из автозагрузки systemd.

Автозапуска скриптов и сервисов с помощью rc.local

Для запуска различных скриптов при загрузке Linux чаще всего используется rc.local.

Но помимо скриптов, через rc.local так же можно и запускать сервисы, даже те, которые запускаются через systemd. Не могу ответить на вопрос, для чего использовать в таком случае rc.local, если есть systemd, но пару примеров я приведу.

Начнем с того, что файл /etc/rc.local должен быть исполняемым:

chmod +x /etc/rc.local

Rc.local должен быть добавлен в автозагрузку systemd:

systemctl enable rc-local

И на примере того же nginx, мы можем добавить в rc.local команду запуска веб-сервера:

service nginx start

rc.local - автозапуск команда в libux centos

Но я редко использую rc.local для запуска сервисов. Чаще rc.local используется, когда нужно запустить скрипт, либо выполнить разово какую-то команду.

К примеру, я создал скрипт /root/test.sh который выполняет некоторые действия, и хочу запустить его сразу после запуска системы. Добавляем в файл rc.local строку:

rc.local запуск sh скрипта

Начиная с CentOS 7, разработчики указывают на то, что rc.local устаревший демон и осуществлять автозапуск скриптов или сервисов через него, это прошлый век. Но пока он работает, я пользуюсь им, так как он очень прост в эксплуатации.

Создание собственного демона и добавление его в systemd

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

Например, нам нужно запускать все тот же скрипт /root/test.sh после перезагрузки системы. Начнем с создания файла нашей будущей службы:

touch /etc/systemd/system/test-script.service
chmod 664 /etc/systemd/system/test-script.service
nano /etc/systemd/system/test-script.service

Содержимое файла будет следующее:

User – пользователь под которым будет запускаться демон

Type=oneshot — процесс будет завершен до запуска дальнейших юнитов

Если вас устроило то, как работает сервис, добавьте его в автозагрузку:

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

Автозапуск через cron

Если вам с какой-то периодичностью нужно запускать скрипт или команду, вы можете воспользоваться cron-ом:

crontab -e — открыть терминал для написания задания cron

И добавьте туда нужное вам задание, например:

* * * * * /root/test.sh — запускать скрипт каждую минуту.

Можно написать скрипт watch-dog, который по заданию будет проверять, например, статус какого-либо сервиса и, если он не работает, запускать его. На нескольких своих проектах я использую подобную схему.

Чтобы вывести список всех заданий в крон, нужно выполнить команду:

Допустимые значения для времени запуска заданий cron по порядку:

  • Минуты от 0 до 59
  • Часы от 0 до 59
  • День месяца от 1 до 31
  • Месяц от 1 до 12
  • День недели от 0 до 7 (0 или 7 это воскресение)

В нашем задании скрипт запускается каждую минуту, поэтому там стоят «*».

Так же вы можете разместить нужный вам скрипт в директориях cron:

Скрипты в указанных директория будут запускаться согласно автоматически подготовленного расписания.

.bashrc: автозапуск скриптов при запуске терминала

Если вам требуется выполнять какие-то действия при запуске терминала ssh, вы можете добавить любую команду или выполнение скрипта в .bash_profile или .bashrc. Теоретически, вы можете добавить какое-либо действие в любой из этих файлов, оно выполнится в любом случае. Обычно все необходимое добавляется в .bashrc, а сам .bashrc запускают из .bash_profile.

Я добавил в файл .bashrc команду на рестарт веб-сервиса nginx:

service nginx restart

.bash_profile - запуск скрипта при старте сессии

После этого сохранил файл и перезапустил терминал:

пример автозапуска скрипта через сессию

Как видите, при запуске терминала, веб-сервер был перезапущен. Какие действия можно выполнять при запуске терминала? Вероятно, запускать какие-то вспомогательные утилиты, например, проверка uptime сервера:

показывать uptime при входе

Или вы хотите, чтобы при запуске терминала, вы сразу попадали в нужную вам директорию и запускали mc, добавьте в .bashrc


Надеюсь эта статья по управлению автозапуском сервисов и скриптов в LInux (статья писалась для CentOS) оказалась полезной для вас. Наверняка тем, кто только познает азы системного администрирования Linux, это информация будет кстати.

Наша компания занимается администрированием веб-серверов на базе CentOS. Довольно часто наши клиенты используют веб-приложения на базе python, ruby или java. Для автозапуска подобных приложений есть готовые шаблоны для написания стартап-скриптов. Но прогресс не стоит на месте, вышел уже второй релиз CentOS 7 и, следуя старой традиции «не ставить dot-zero релизы на продакшен», мы начинаем предлагать клиентам сервера на базе CentOS 7.1 (1503).

В CentOS7, так же как и в его родителе RHEL7, используется systemd — менеджер системы и служб для Linux, совместимый со скриптами инициализации SysV и LSB. systemd обеспечивает возможности агрессивной параллелизации и много всего прочего.

image

Огромный монстр с множеством возможностей, гибкими настройками и мегабайтами документации…

Но что делать, если стоит задача быстро-быстро, вот прямо вчера, сделать автозапуск некоего сервиса?
Давайте выжмем из документации минимально необходимый набор информации для создания простых старт-стоп скриптов.

Systemd запускает сервисы описанные в его конфигурации.
Конфигурация состоит из множества файлов, которые по-модному называют юнитами.

Все эти юниты разложены в трех каталогах:

/usr/lib/systemd/system/ – юниты из установленных пакетов RPM — всякие nginx, apache, mysql и прочее
/run/systemd/system/ — юниты, созданные в рантайме — тоже, наверное, нужная штука
/etc/systemd/system/ — юниты, созданные системным администратором — а вот сюда мы и положим свой юнит.

Юнит представляет из себя текстовый файл с форматом, похожим на файлы .ini Microsoft Windows.

[Название секции в квадратных скобках]
имя_переменной = значение

Для создания простейшего юнита надо описать три секции: [Unit], [Service], [Install]

В секции Unit описываем, что это за юнит:
Названия переменных достаточно говорящие:

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

Запускать юнит после какого-либо сервиса или группы сервисов (например network.target):

After=syslog.target
After=network.target
After=nginx.service
After=mysql.service

Для запуска сервиса необходим запущенный сервис mysql:

Для запуска сервиса желателен запущенный сервис redis:

В итоге переменная Wants получается чисто описательной.
Если сервис есть в Requires, но нет в After, то наш сервис будет запущен параллельно с требуемым сервисом, а не после успешной загрузки требуемого сервиса

В секции Service указываем какими командами и под каким пользователем надо запускать сервис:

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

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

Также следует определить PIDFile=, чтобы systemd могла отслеживать основной процесс:


Рабочий каталог, он делается текущим перед запуском стартап команд:

Пользователь и группа, под которым надо стартовать сервис:

Запрет на убийство сервиса вследствие нехватки памяти и срабатывания механизма OOM:
-1000 полный запрет (такой у sshd стоит), -100 понизим вероятность.

Команды на старт/стоп и релоад сервиса

ExecStart=/usr/local/bin/bundle exec service -C /work/www/myunit/shared/config/service.rb --daemon
ExecStop=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state stop
ExecReload=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state restart

Тут есть тонкость — systemd настаивает, чтобы команда указывала на конкретный исполняемый файл. Надо указывать полный путь.

Таймаут в секундах, сколько ждать system отработки старт/стоп команд.

Попросим systemd автоматически рестартовать наш сервис, если он вдруг перестанет работать.
Контроль ведется по наличию процесса из PID файла

В секции [Install] опишем, в каком уровне запуска должен стартовать сервис

multi-user.target или runlevel3.target соответствует нашему привычному runlevel=3 «Многопользовательский режим без графики. Пользователи, как правило, входят в систему при помощи множества консолей или через сеть»

Вот и готов простейший стартап скрипт, он же unit для systemd:
myunit.service


Кладем этот файл в каталог /etc/systemd/system/

Смотрим его статус systemctl status myunit


Видим, что он disabled — разрешаем его
systemctl enable myunit
systemctl -l status myunit

Если нет никаких ошибок в юните — то вывод будет вот такой:

Запускаем сервис
systemctl start myunit

Смотрим красивый статус:
systemctl -l status myunit

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

Читайте также: