====== Запуск 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}}