systemctl показывает неактивный / мертвый, но служба работает

Я хотел бы управлять сервером TeamSpeak 3 с помощью systemd (systemctl).

Когда я запускаю / останавливаю / перезапускаю сервер TeamSpeak 3 с помощью команды systemctl, systemctl возвращает правильный статус:

$ systemctl status ts3server.service
● ts3server.service - TeamSpeak 3 Server
   Loaded: loaded (/etc/systemd/system/ts3server.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2019-02-12 23:15:18 CET; 1min 11s ago
 Main PID: 842 (ts3server)
   CGroup: /system.slice/ts3server.service
           └─842 ./ts3server inifile=ts3server.ini

Feb 12 23:15:18 hostname.local systemd[1]: Starting TeamSpeak 3 Server...
Feb 12 23:15:18 hostname.local ts3server_startscript.sh[838]: Starting the TeamSpeak 3 server
Feb 12 23:15:18 hostname.local ts3server_startscript.sh[838]: TeamSpeak 3 server started, for details please view the log file
Feb 12 23:15:18 hostname.local systemd[1]: Started TeamSpeak 3 Server.

Но когда служба останавливается иным образом (например, посредством автоматического обновления), а затем запускается снова - без systemctl - systemctl status Команда возвращает неверный статус:

$ systemctl status ts3server.service
● ts3server.service - TeamSpeak 3 Server
   Loaded: loaded (/etc/systemd/system/ts3server.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Mon 2019-02-11 03:15:16 CET; 1 day 19h ago
Condition: start condition failed at Mon 2019-02-11 03:15:16 CET; 1 day 19h ago
           └─ ConditionPathExists=!/home/teamspeak/.update.lock was not met
  Process: 21740 ExecStop=/home/teamspeak/ts3server_startscript.sh stop (code=exited, status=0/SUCCESS)
  Process: 29220 ExecStart=/home/teamspeak/ts3server_startscript.sh start (code=exited, status=0/SUCCESS)
 Main PID: 29224 (code=exited, status=0/SUCCESS)

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

Файл PID существует в данный момент:

$ stat /home/teamspeak/ts3server.pid
  File: /home/teamspeak/ts3server.pid
  Size: 4              Blocks: 8          EA Block: 4096   regular file
Device: ca01h/51713d     Inode: 534471      Symbolic Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1001/teamspeak)   Gid: ( 1001/teamspeak)
Access    : 2019-02-12 23:15:09.192927211 +0100
Modified: 2019-02-12 23:15:09.188927218 +0100
Changed   : 2019-02-12 23:15:09.188927218 +0100
 Birth    : -

Процесс с этим PID запущен, и я могу подключиться к этому серверу TeamSpeak 3.

/home/teamspeak/.update.lock существует во время процесса автоматического обновления. После обновления файл удаляется / удаляется и больше не существует.

systemctl показывает правильный статус, когда я убиваю работающий сервис PID как systemctl перезапускает сервис, используя systemd правильно позже.

Вот мой /etc/systemd/system/ts3server.service файл:

[Unit]
Description=TeamSpeak 3 Server
After=network.target mysqld.service
ConditionPathExists=!/home/teamspeak/.update.lock

[Install]
WantedBy=multi-user.target
Alias=ts3server.service

[Service]
User=teamspeak
Group=teamspeak
WorkingDirectory=/home/teamspeak/
ExecStart=/home/teamspeak/ts3server_startscript.sh start
ExecStop=/home/teamspeak/ts3server_startscript.sh stop
ExecReload=/home/teamspeak/ts3server_startscript.sh restart
PIDFile=/home/teamspeak/ts3server.pid
Restart=always
Type=forking

Почему может systemctl не вернуть правильный статус, хотя сервер TeamSpeak 3 запущен правильно по-другому?

4 ответа

Вы должны изменить Type в simple в вашем модуле файл, и он будет работать. IIRC forking требует явного вызова fork() метод, в то время как вы запускаете его из скрипта bash и просто нет fork() вызов.

Ответ на ваш вопрос "почему" заключается в том, что systemd ищет известный ему PID (842 в приведенном выше примере), но не отслеживает собственную информацию PID службы. Если этот процесс больше не выполняется, systemd не знает, что происходит с этим процессом. Он также не может перезапустить его (поскольку порты уже будут связаны новым экземпляром).

Вероятно, более чистый способ сделать обновление

  1. Используйте systemctl, чтобы остановить службу
  2. Выполните обновление, а затем
  3. Используйте systemctl, чтобы начать процесс.

использоватьsystemctl --user get-defaultчтобы получить цель по умолчанию

      $ systemctl --user get-default
default.target

изменять

      WantedBy=default.target

Хитрость заключается в том, чтобы указать Type=oneshot и RemainAfterExit=yes и не указывать PIDFile=

Минимальный пример:

[Unit]
Description=service that is restarted by externalities.

[Service]
Type=oneshot
RemainAfterExec=yes
ExecStart=/startup.sh
ExecStop=/stop.sh

[Install]
WantedBy=multi-user.target

В документации это называется "Остановка одним выстрелом".

Подобно сервисам с одним выстрелом, иногда есть единицы, которым необходимо выполнить программу, чтобы что-то настроить, а затем выполнить другую, чтобы закрыть это, но ни один процесс не остается активным, пока они считаются "запущенными".

Но они не рассматривают вариант использования, когда запущенная программа изменяет значения PID, даже если она работает и для этого.

Другие вопросы по тегам