У меня появился Linux на домашнем компьютере, и я поспешил обжиться в новой ОС. Она была установлена с systemd init process. Это было мое первое знакомство с этим новым инструментом. Cвой ноутбук я использую для каждодневной жизни и для программирования. Мне хотелось включать рабочие программы (Apache2 и MySQL) только на время, пока я их использую, чтобы не тратить впустую ресурсы своего компьютера.
Дополнительно, для тестирования я написал bash скрипт, который выгружает содержимое одной из MySQL БД c жесткого диска в ОЗУ (в tmpfs) – так тесты выполняются значительно быстрее. По идее, я мог бы начинать свой рабочий день вот так:
systemctl start apache2.service systemctl start mysqld.service /root/scripts/mysqld-tmpfs start
И заканчивать его:
systemctl stop apache2.service systemctl stop mysqld.service /root/scripts/mysqld-tmpfs stop
Но мне хотелось сделать вещи “как надо”.
Чего я хотел?
- Мне было лень писать 2 команды (запуск apache и запуск mysql), т.к. я знал, что обе программы всегда будут выключаться и включаться синхронно. Хотелось выполнять эту операцию одной командой.
- Дело попахивало неприятностями, если компьютер перезагрузится пока моя база данных будет сидеть в tmpfs – все файлы будут потеряны. Конечно, я делал бекапы, но мне опять же было лень восстанавливать их вручную после каждой непредвиденной перезагрузки.
Что я сделал?
В итоге я объединил Apache2 и MySQL в один target. Это позволило запускать оба сервиса одной командой. А свой mysqld-tmpfs скрипт я декларировал в виде сервиса в глазах systemd. Будучи сервисом, я уверен, что systemd выполнит его корректную остановку, если система пойдет на перезагрузку или еще в какую-то нештатную ситуацию, и моя БД без потерь сохранится на жесткий диск.
Администрирование Linux (Ubuntu). Урок 9 Управление сервисами с помощью systemd
Что такое service?
Это некоторая программа, которая выполняется в фоне и предоставляет полезную функциональность. К примеру, Apache веб сервер. Сервисы можно запускать и останавливать. Некоторые сервисы могут запускаться и останавливаться автоматически по определенным событиям (загрузка ОС, выгрузка ОС и тп). Так же их можно запускать/останавливать вручную.
Сервис декларируется в /etc/systemd/system/my-name.service файлах (с суффиксом “.service”).
Что такое target?
Target в systemd очень похож на runlevel в openRC, но это все-таки разные вещи. Во-первых, target позволяет группировать 1 и более сервисов в единый блок. Группируя сервисы в targets, ими проще управлять. Во-вторых, systemd автоматически включает/выключает targets по событиям. “Включение” target означает включение всех сервисов, которые он объединяет в себе. К примеру, если в systemd настроен target по умолчанию my-favorite.target, то при загрузке системы systemd включит все сервисы, которые задекларированы внутри my-favorite.target. В какой-то момент в консоли можно набрать:
systemctl isolate my-another.target
Все сервисы из my-another.target будут включены, и все включенные сервисы не из my-another.target будут выключены. Это очень похоже на переключение runlevel в openRC. Однако, systemd поддерживает включение более чем 1 target. Вот пример:
Изменение и создание unit systemd. Как написать свою службу в Linux?
# Эксклюзивно включаем my-favorite.target и выключаем все остальные сервисы systemctl isolate my-favorite.target # К уже запущенным сервисам и targets добавляем еще 1 target systemctl start my-another.target
После выполнения этих команд в системе будет работать объединение сервисов из my-favorite.target и my-another.target.
Как я это сделал?
В итоге у меня получился вот такой mysqld-tmpfs.service файл:
Description=Mount a MySQL database into tmpfs. # Мой /root/scripts/tmpfs скрипт может работать как при включенном, так и при выключенном mysql сервисе. Но если бы mysql сервис нужен был включенным, к примеру, то я бы добавил эти строки: #Requires=mysqld.service #After=mysqld.service [Service] # Даем знать systemd, что этот сервис представляет из себя лишь 1 процесс. Man page хорошо описывает доступные опции. Type=oneshot # Выполнить эту команду при запуске сервиса. ExecStart=/root/scripts/mysqld-tmpfs start # Выполнить эту команду при остановке сервиса. ExecStop=/root/scripts/mysqld-tmpfs stop # Даем знать systemd, что сервис нужно считать запущенным, даже если основной процесс прекратил свою работу. Как раз то, что мне нужно: мой процесс выполнит монтировку и после этого прекратит свою работу, но должен считаться активным, т.к. монтировка осталась в системе. RemainAfterExit=yes
И вот такой programming.target файл:
[Unit] Description=Working/Programming target Requires=mysqld.service Requires=apache2.service # Сюда я могу дописывать новые сервисы “Requires=another.service”, если они мне понадобятся в повседневной работе.
Какие были проблемы?
- Запустится какой-то другой сервис, который в своей декларации указывает, что он конфликтует с нашим сервисом.
- Выполнится systemctl isolate some-another.target или systemctl stop this.service.
- Наш сервис может запросить в своей декларации останавливать себя не ленивым образом, а активным, добавив вот такую строку в [Unit] секцию: StopWhenUnneeded=true
Декларации “чужих” сервисов можно менять создавая файлы /etc/systemd/system/name-i-alter.service.d/*.conf. Я просто создал /etc/systemd/system/apache2.service/auto-stop.conf и /etc/systemd/system/mysqld.service.d/auto-stop.conf и поместил туда ту строку.
Другая проблема, на которую я, наткнулся была в том, что systemd не очень любит symlinks. Я не большой любитель “загаживать” системные директории типа /etc, /bin, /usr своими локальными продуктами жизнедеятельности, поэтому изначально я попытался свой /etc/systemd/system/mysqld-tmpfs.service сделать symlink на /root/scripts/mysqld-tmpfs.service файл, т.е. хранить сам файл в домашнем каталоге root пользователя. Но systemctl команда отказывалась работать с таким сервисом выдавая малопонятные ошибки. Оказалось, что определенную часть своей внутренней кухни systemd делает именно на symlinks, и ему тогда “трудно” отличать внутреннюю кухню (свои symlinks) от сторонних *.service файлов (если они тоже являются symlinks). Удалив symlink из /etc/systemd/system/mysqld-tmpfs.service и скопировав туда содержимое настоящего файла, я решил эту проблему. Более подробное описание этой проблемы можно прочитать тут: bugzilla.redhat.com/show_bug.cgi?id=955379
Результат
Я достиг своей цели. Начиная рабочий день:
systemctl start programming.target
Когда нужно выполнить тесты на своем проекте:
systemctl start mysqld-tmpfs.service
Когда я хочу демонтировать БД из tmpfs в жесткий диск (хотя на практике я так почти не делаю, а просто оставляю БД в tmpfs на целый день, и при выключении systemd за меня запускает демонтировку из tmpfs в жесткий диск):
systemctl stop mysqld-tmpfs.service
Когда я закончил работать и хочу остановить рабочие программы:
systemctl stop programming.target
Cheat sheet
- Вызывайте systemctl daemon-reload, если вы изменили декларацию чего-либо (systemd считает файлы декларации заново)
- systemctl start my-name.(service|target) – запуск сервиса или target
- systemctl stop my-name.(service|target) – остановка сервиса или target
- systemctl enable my-name.service – сервисы могут декларировать при каких включенных targets они должны включаться. Для этого используется [Install] секция в файле декларации сервиса. Вы, как сисадмин, имеете власть на установку этого “пожелания” сервиса. Часто сервисы “устанавливаются” в target по умолчанию multi-user.target или в похожее.
- systemctl disable my-name.service – обратная операция по отношению к enable: деассоциировать связь между my-name.service и targets, которые он запросил в [Install] секции своей декларации.
- systemctl isolate my.target — включить все сервисы из my.target и выключить все остальные включенные сервисы.
- systemctl status my-name.(service|target) — узнать статус (запущен/остановлен) у сервиса или target.
Надеюсь, эта статья кому-то поможет при осваивании systemd. Я попытался сделать ее компактной, и если упустил из внимания какие-то дополнительные вопросы, спрашивайте в комментариях!
- Настройка Linux
- Системное администрирование
- *nix
- Серверное администрирование
Источник: habr.com
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Cancel Create
docLinux / articles / Создание службы Linux с помощью systemd.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cannot retrieve contributors at this time
134 lines (87 sloc) 7.78 KB
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents Copy raw contents
Copy raw contents
Создание службы Linux с помощью systemd
При написании веб-приложений мне часто приходится выгружать сложные вычислительные задачи в асинхронный рабочий сценарий, планировать задачи на потом или даже писать демон, который прослушивает сокет для прямой связи с клиентами.
В то время как иногда могут быть более эффективные инструменты для работы — всегда рассматривайте сначала использование существующего программного обеспечения, например, сервер очереди задач — написание собственной службы может дать вам уровень гибкости, который вы никогда не получите, когда связаны ограничениями стороннего программного обеспечения.
Круто то, что создать службу Linux довольно легко: используйте свой любимый язык программирования для написания долго работающей программы и превратите ее в службу с помощью systemd.
Давайте создадим небольшой сервер с использованием PHP. Я вижу, как твои брови поднимаются, но это работает на удивление хорошо. Мы прослушаем UDP-порт 10000 и вернем любое сообщение, полученное с помощью преобразования ROT13:
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); socket_bind($sock, ‘0.0.0.0’, 10000); for (;;) < socket_recvfrom($sock, $message, 1024, 0, $ip, $port); $reply = str_rot13($message); socket_sendto($sock, $reply, strlen($reply), 0, $ip, $port); >
Давайте начнем это:
$ php server.php
И проверить это в другом терминале:
$ nc -u 127.0.0.1 10000 Hello, world! Uryyb, jbeyq!
Круто, все работает. Теперь мы хотим, чтобы этот сценарий выполнялся постоянно, перезапускался в случае сбоя (неожиданного выхода) и даже выживал после перезапуска сервера.
Вот где systemd вступает в игру.
Превращение в сервис
Давайте создадим файл с именем /etc/systemd/system/rot13.service :
[Unit] Description=ROT13 demo service After=network.target StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=1 User=centos ExecStart=/usr/bin/env php /path/to/server.php [Install] WantedBy=multi-user.target
- установите действительное имя пользователя после User=
- установите правильный путь к вашему сценарию в ExecStart=
Вот и все. Теперь мы можем запустить сервис:
$ systemctl start rot13
И автоматически заставить его запускаться при загрузке:
$ systemctl enable rot13
Теперь, когда ваш сервис (надеюсь) работает, может быть важно немного углубиться в параметры конфигурации и убедиться, что он всегда будет работать так, как вы ожидаете.
Начиная в правильном порядке
Возможно, вы задавались вопросом, что сделала директива After= . Это просто означает, что ваш сервис должен быть запущен после того, как сеть готова. Если ваша программа ожидает, что сервер MySQL запущен и работает, вы должны добавить:
After=mysqld.service
Перезапуск при выходе
По умолчанию systemd не перезапускает ваш сервис, если программа по какой-либо причине завершает работу. Обычно это не то, что вам нужно для службы, которая должна быть всегда доступна, поэтому мы советуем ей всегда перезапускаться при выходе:
Restart=always
Вы также можете использовать on-fault только для перезапуска, если состояние выхода не равно 0 .
По умолчанию systemd пытается перезапустить через 100 мс. Вы можете указать количество секунд ожидания перед попыткой перезапуска, используя:
RestartSec=1
Как избежать ловушки: предел начала
Я лично попадал в это не раз. По умолчанию, когда вы настраиваете Restart=always , как мы это делали, **systemd прекращает перезапуск службы, если она не запускается более 5 раз в течение 10 секунд **. Навсегда.
За это отвечают две [Unit] конфигурации опции:
StartLimitBurst=5 StartLimitIntervalSec=10
Директива RestartSec также влияет на результат: если вы установите перезапуск через 3 секунды, то вы не сможете достичь 5 неудачных попыток в течение 10 секунд.
**Простое исправление, которое всегда работает, — установить StartLimitIntervalSec=0 . ** Таким образом, systemd будет пытаться перезапустить ваш сервис навсегда.
Хорошей идеей будет установить RestartSec как минимум на 1 секунду, чтобы избежать чрезмерной нагрузки на сервер, когда что-то пойдет не так.
В качестве альтернативы вы можете оставить настройки по умолчанию и попросить systemd перезапустить ваш сервер, если достигнут предел запуска, используя StartLimitAction=reboot .
Это действительно так?
Вот и все, что нужно для создания службы Linux с помощью systemd: написание небольшого файла конфигурации, который ссылается на вашу давно работающую программу.
В течение нескольких лет Systemd была стандартной системой инициализации в RHEL / CentOS, Fedora, Ubuntu, Debian и других, поэтому есть вероятность, что ваш сервер готов к размещению ваших доморощенных сервисов!
Источник: github.com
Systemd: Создание Сервиса — Примеры
Большинство дистрибутивов Linux в качестве менеджера системы и сервисов используют systemd.
systemctl является основной командой для управления сервисами в systemd.
В данной статье я покажу, как создать service-файл в systemd, который позволит управлять вашим сервисом с помощью команды systemctl, как без перезагрузки перезапустить systemd, чтобы он перечитал unit-файлы и как активировать ваш новый сервис.
Также я приведу описание наиболее важных опций используемых в service-файлах с примерами реальных service-файлов.
- 1 Создание Сервиса в Systemd
- 2 Опции Service-файла в Systemd
- 2.1 Важные Опции Секции [Unit]
- 2.2 Важные Опции Секции [Install]
- 2.3 Важные Опции Секции [Service]
Создание Сервиса в Systemd
Создайте service-файл /etc/systemd/system/foo-daemon.service (замените foo-daemon на имя вашего сервиса):
Источник: darksf.ru