https://linux-notes.org/pishem-systemd-unit-fajl/
После загрузки кернел запускает /sbin/init АКА systemd
/sbin/init -> ../usr/lib/systemd/systemd
systemd загружает описание сервисов, таргетов и т.д. из unit-файлов в каталогах
/etc/systemd/system/ и /usr/lib/systemd/system/
target == список/комплект желаемых севисов
и запускает все, что определяется таргетом default.target
Обычно default.target -> /usr/lib/systemd/system/graphical.target
multi-user.target == соответствует многопользовательскому режиму без графики
graphical.target == multi-user.target + display-manager.service
# Сменить дефолтный таргет на постоянку:
systemctl set-default multi-user.target # загружаться в текстовый login
systemctl set-default graphical.target # загружаться в графический login
Чтоб при загрузке разово попасть в альтернативный (не дефолтный таргет)
в строку начальной загрузки добавить что-то типа:
systemd.unit=multi-user.target
systemctl status serv-name # Статус сервиса
systemctl show serv-name # Полное описание сервиса
journalctl -u serv-cename -f # Логи сервиса
systemctl start serv-name # Старт / стоп
systemctl stop serv-name
systemctl enable serv-name # Поставить на автостарт при загрузке
systemctl disable serv-name
systemctl cat serv-name # Посмотреть unit-файл сервиса
systemctl daemon-reload # Перечитать конфиги и unit'ы если они менялись
systemctl list-dependencies multi-user.target # посмотреть кто таргете
systemctl enable/disable name.service # в(ы)ключает сервис в "родной" таргет
# "Родной" таргет сервису прописывается в [Install] WantedBy=multi-user.target
Пример простого unit-файла для сервиса
# /etc/systemd/system/squid_proxy.service
[Unit]
Description=SSH Port Forwarding to 110:1110, 3128:3128 from 2022:22
After=network.target squid
[Service]
User=ivanov
# Переменные окружения можно задать Environment= или всосать из файла
Environment=APP_USER=ivanov
EnvironmentFile=/home/ivanov/service.conf
ExecStart=/home/${APP_USER}/bin/squid_proxy host.ru
ExecStop=/home/${APP_USER}/bin/squid_proxy --stop %H %n
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=15
[Install]
WantedBy=multi-user.target
#############################################################
Директивы в Unit-файлах для systemd
systemd.unit(5)
systemd.service(5)
After,Before последовательность запуска при _одновременном_ старте
Wanted= попытается запустить желаемое, если не получится - не страшно
Requires= запустит желаемое, если не получится - отменит свой запуск
В секции [Install] # При enable сервис залинкуют в multy-user.target.wants
WantedBy=multy-user.target
Restart= no|on-success|on-failure|on-abnormal|on-watchdog|on-abort|always
RestartSec=15
Список поиска unit-файлов (на сам деле он гораздо длиннее)
/etc/systemd/system/
/usr/lib/systemd/system/
Type=forking Долгая программа сама уходит в bg, только верхний ExecStart
oneshot Короткая. Допустимо несколько ExecStart
simple Программа в fg, systemd ее ждет. Работает лишь верхний ExecStart
# Если команда запуска/презапуска вернула ошибку - остальные не выполняются
ExecStartPre=Command1 Подготовительные команды
ExecStartPre=-Comand2 "-" перед - означает код возврата не учитывать
ExecStart= Главная команда (одна)
ExecStartPost= Завершающие команды, отрабатывают после завершения Главной
%H %l Hostname и ShortHostname
%n %N Full Unit Name и unit-name без суффикса
$MAINPID PID сервиса; используется в ExecStop= ExecReload=
$SERVICE_RESULT Результат завершения сервиса; особенно полезен в ExecStopPost=
$EXIT_CODE Способ завершения процесса: code, signal или пусто
$EXIT_STATUS Код выхода или номер сигнала
systemd-path search-binaries-default # посмотреть путь поиска для ExecStart
ExecSearchPath=/opt/my-app/bin:/usr/local/bin # задать свой путь поиска
Редактирование системного unit-файла
Обычно они лежат в /usr/lib/systemd/system/ и могут обновляться при апдейтах.
# systemctl cat sluzhba.service
1. Копируем unit в /etc/systemd/system и редактируем как нам угодно
# systemctl cat sluzhba.service > /etc/systemd/system/sluzhba.service
# vi /etc/systemd/system/sluzhba.service
либо воспользовавшись командой
# systemctl edit --full myapp.service # она сохранит в /etc/systemd/system/
2. Создаем "drop-in" директорию сервиса и кладем в нее файлы.conf с поправками
# mkdir /etc/systemd/system/sluzhba.service.d
Пример /etc/systemd/system/sluzhba.service.d/050add.conf
[Unit]
# директивы будут добавлены к оригинальному unit-файлу
After=memcached.service
Requires=memcached.service
# Чтоб не добавить а заменить, сперва обнуляем директиву
AssertPathExists=
AssertPathExists=/srv/www
[Service]
PrivateTmp=yes
3. systemctl edit - сама создаст дроп-ин директорию
systemctl edit myapp.service # все некомментированное ВВЕРХУ попадет drop-in
systemctl show myapp.service # смотрим действующие значения юнита
systemctl revert myapp.service # myapp.service.d
# Чтоб не лез неправильный пагер и редактор, sudo -E, либо вписать в sudoers
Defaults env_keep += "SYSTEMD_EDITOR EDITOR VISUAL"
Делаем одноименные юниты: socket и service. Сокет слушает порт, когда
приходит клиент - автоматически запускает сервис и передает ему соединение.
Два вида передачи:
Accept=yes на каждый коннект отдельный запуск, соединение передается на stdin
Accept=no долговременный запуск, listen() передается как FD 3
остальные коннекты сервис принимает сам, выдавая на них accept()
# ListenStream=/run/my.sock
# ListenDatagram=1.2.3.4:8080
# Service=name-pro.service
ListenStream=3306
Делаем [name@.service|name.service]
[Service]
ExecStart=/usr/bin/name-pro
StandardOutput=socket
StandardInput=socket
Прямой аналог - xinetd stream wait=no (параллельное обслуживание)
Unit назвать name@.service (для множественных запусков)
##### name.socket ########## может слушать tcp/udp/unix-socket
# ListenDatagram=1.2.3.4:8080
# ListenStream=/var/run/name.socket
[Socket]
ListenStream=3306
##### name@.service ###### @ - сервисный шаблон - т.к. их порождается много
[Service]
ExecStart=/usr/bin/name-pro
# Accept=yes ОБЯЗАН иметь назначение I/O на socket, иначе I/O в /dev/null
StandardOutput=socket
StandardInput=socket
# Количество одновременных коннектов можно ограничивать
MaxConnections=
MaxConnectionsPerSource=
Сервис обязан умееть работать с сетью.
На каждый коннект сервис запускается заново, получает соединение на stdin.
При завершении клиента - в сервис идет EOF, он должен завершить работу,
иначе он останется zomby.
Аналог - xinetd stream wait=yes
Unit назвать name.service (монопольный запуск). Программа сама делает accept()
Bind() и Listen() делает systemd. При первом коннекте запускает сервис,
пробрасывает ему listen как FD 3. Дальше все коннекты идут в сервис, на
каждый он дает accept, множественность за счет сервиса, остальные коннекты
он подбирает accept(). Должен крутить вечный цикл while True { accept() }
##### name.socket ########## может слушать tcp / udp / unix-socket
[Socket]
ListenStream=3306
Service=name
# Если имя сокета не совпадает с сервисом, сервис надо указать в Service=
##### name.service ###### Одиночный service-юнит
[Service]
ExecStart=/usr/bin/name-long
# Input/Output не задаем, соединения сервис добывает сам, посредством accept()
Sshd умеет 3 варианта: standalone, socket-activation Accept=yes и Accept=no
systemctl disable sshd.service
systemctl enable sshd.socket
# /usr/lib/systemd/system/sshd.socket ##########################
[Unit]
Description=OpenSSH Server Socket
Conflicts=sshd.service
[Socket]
ListenStream=22
Accept=yes
# Accept=yes == одноразовые sshd -i
[Install]
WantedBy=sockets.target
# /usr/lib/systemd/system/sshd@.service ##########################
[Unit]
Description=OpenSSH Per-Connection Server Daemon
After=network.target
[Service]
EnvironmentFile=-/etc/sysconfig/ssh
ExecStartPre=/usr/sbin/sshd-gen-keys-start
ExecStart=-/usr/sbin/sshd -i $SSHD_OPTS
StandardInput=socket
Делаем emergency dropbear-sshd как сервис
Чтобы при попадании в emergency.target (когда boot застревает на раннем
этапе и просит пароль root), атоматически запускался Dropbear-sshd
Нужно: 1) добыть бинарник и ssh-ключи 2) создать systemd-сервис
3) заенаблить его в emergency.target 4) дырку в firewall
rpm -i dropbear-*.x86_64.rpm # устанавливаем из rpm
systemctl start dropbear-keygen # генерим хост-ключи в /etc/dropbear
Или компилим из сурсов
tar xjvf dropbear-2026.94.tar.bz2 ; cd dropbear-2026.94
./configure [ --enable-static ] # --enable-static необязателен
make ; strip dropbear
make -n install # make install либо руками копирнуть в /sbin
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
dropbearkey -t ed25519 -f /etc/dropbear/dropbear_ed25519_host_key
dropbearkey -t ecdsa -s 256 -f /etc/dropbear/dropbear_ecdsa_host_key
# /etc/systemd/system/dropbear-emergency.service
[Unit]
Description=Dropbear Emergency SSH Service -- 2222
DefaultDependencies=no
Conflicts=shutdown.target multi-user.target graphical.target
After=local-fs.target
[Service]
Type=forking
ExecStartPre=-ip link set lo up
ExecStartPre=-ip link set eth0 up
ExecStartPre=-ip addr add 192.168.1.10/24 dev eth0
ExecStart=/sbin/dropbear -p 192.168.1.10:2222
User=root
[Install]
WantedBy=emergency.target
#####################################################################
systemctl enable dropbear-emergency
firewall-cmd --add-port=2222/tcp --permanent # [ --zone=internal ]
Популярность: 2, Last-modified: Wed, 30 Sep 2026 19:01:28 GmT