====== Запуск nodejs приложения через systemd ======
У [[https://en.wikipedia.org/wiki/Systemd|systemd]] много хейтеров, но чем больше я с ним встречаюсь по рутинным админским делам, тем больше он мне нравится.
Задача: запустить nodejs приложение в Debian 9 без смузи node менеджеров.
Требования:
* Чтобы рестартилось
* Чтобы был лог
* Чтобы [[https://ru.wikipedia.org/wiki/KISS_(принцип)|KISS]]
Рабочая директория ''/usr/local/foobar'', имя приложения ''spacex.js''
Вероятно когда-нибудь я попробую node менеджеры ([[http://strong-pm.io/compare/|сравнение]])
* [[http://strong-pm.io/compare/|StrongLoop]]
* [[https://github.com/foreversd/forever|Forever]]
* [[http://pm2.keymetrics.io/docs/usage/quick-start/|PM2]]
===== service файл =====
Создадим systemd сервис файл **spacex.service** в директории ''/etc/systemd/system/''.
[Unit]
Description=SpaceX simulator service
# Запускать сервис после сервиса mysql
Requires=After=mysql.service
# Доки
Documentation=https://elonmusk.guru
[Service]
ExecStart=/usr/bin/node /usr/local/foobar/spacex.js
# Не всегда требуется, но лучше указать
WorkingDirectory=/usr/local/foobar
# Об этом чуть ниже
Restart=always
# Перезапустить сервис через 10 секунд
RestartSec=10
# А можно даже так
# RestartSec=500ms
# Вести журнал в syslog
StandardOutput=syslog
StandardError=syslog
# Идентификатор нашего сервиса
SyslogIdentifier=AdventureTime
#User=dx
#Group=dx
Environment=NODE_ENV=production PORT=3000
[Install]
WantedBy=multi-user.target
**Restart** может принимать значения always или on-failure
На самом деле больше: https://www.freedesktop.org/software/systemd/man/systemd.service.html
^ Restart settings/Exit causes | no | always | on-success | on-failure | on-abnormal | on-abort | on-watchdog |
| Clean exit code or signal | | X | X | | | | |
| Unclean exit code | | X | | X | | | |
| Unclean signal | | X | | X | X | X | |
| Timeout | | X | | X | X | | |
| Watchdog | | X | | X | X | | X |
Если установлено значение always, служба будет перезапущена независимо от того, была ли она завершена корректно или нет.
Далее как обычно для systemd
# systemctl daemon-reload
# systemctl enable spacex.service
# systemctl start spacex.service
===== Журналирование =====
Отдельно поговорим о логах.
Я решил записывать всё в отдельные лог файлы и по первому примеру из гугла сделал так
StandardOutput=file:/var/log/adventure_time.log
StandardError=file:/var/log/adventure_time_error.log
Оказалось, что нужен systemd поновее чем предлагает Debian 9.
# systemctl --version
systemd 232
В [[https://github.com/systemd/systemd/pull/7198|новых версиях systemd]] (236+) можно использовать путь к файлу. В версии 240 появился [[https://lists.freedesktop.org/archives/systemd-devel/2018-December/041852.html|новый параметр append]].
===== systemd + rsyslog =====
Рабочий вариант ([[https://web.archive.org/web/20180330104136/http://wiki.rsyslog.com/index.php/Filtering_by_program_name|спасибо rsyslog wiki и webarchive]]). Будем отправлять stdout/stderr в syslog с определенным идентификатором (опция **SyslogIdentifier**).
systemd unit service файл
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=AdventureTime
Подразумевается, что логами управляет rsyslog. Создаём файл ''/etc/rsyslog.d/at.conf''
if $programname == 'AdventureTime' then /var/log/adventure_time.log & stop
Даем права на запись
chown root:adm /var/log/adventure_time.log
Перезапускаем rsyslog
# systemctl restart rsyslog
Теперь логи можно смотреть и через journalctl и в отдельном log файле.
# journalctl -u AdventureTime
Дополнительное чтиво для любопытных - [[https://jdebp.eu/FGA/systemd-house-of-horror/|The systemd house of horror. Examples of how people commonly use systemd in an egregiously wrong manner.]]
===== Ошибки =====
==== Error: ENOSPC: System limit for number of file watchers reached ====
Проверить текущее значение
cat /proc/sys/fs/inotify/max_user_watches
Значения по-умолчанию (Debian 12)
sysctl fs.inotify
fs.inotify.max_queued_events = 16384
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 29464
Создаём файл ''/etc/sysctl.d/99-inotify.conf''
fs.inotify.max_user_instances=256
fs.inotify.max_user_watches=524288
fs.inotify.max_queued_events=32768
применяем изменения
sysctl --system
Подробнее про [[https://linux.die.net/man/7/inotify|inotify(7)]] - Linux man page
The following interfaces can be used to limit the amount of kernel memory consumed by inotify:
**/proc/sys/fs/inotify/max_queued_events**
The value in this file is used when an application calls [[https://linux.die.net/man/2/inotify_init|inotify_init]](2) to set an upper limit on the number of events that can be queued to the corresponding inotify instance. Events in excess of this limit are dropped, but an **IN_Q_OVERFLOW** event is always generated.
**/proc/sys/fs/inotify/max_user_instances**
This specifies an upper limit on the number of inotify instances that can be created per real user ID.
**/proc/sys/fs/inotify/max_user_watches**
This specifies an upper limit on the number of watches that can be created per real user ID.
{{tag>linux debian systemd nodejs rsyslog}}