Содержание
Запуск nodejs приложения через systemd
У systemd много хейтеров, но чем больше я с ним встречаюсь по рутинным админским делам, тем больше он мне нравится.
Задача: запустить nodejs приложение в Debian 9 без смузи node менеджеров.
Требования:
- Чтобы рестартилось
- Чтобы был лог
- Чтобы KISS
Рабочая директория /usr/local/foobar
, имя приложения spacex.js
Вероятно когда-нибудь я попробую node менеджеры (сравнение)
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
В новых версиях systemd (236+) можно использовать путь к файлу. В версии 240 появился новый параметр append.
systemd + rsyslog
Рабочий вариант (спасибо 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
Дополнительное чтиво для любопытных - 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
Подробнее про 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 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.
Обсуждение