systemctl shows inactive / dead, but service is running

I would like to manage a TeamSpeak 3 server with systemd (systemctl).

When I start / stop / restart the TeamSpeak 3 server using systemctl command, systemctl is returning the correct status:

$ 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.

But when the service is stopped otherwise (eg. through an automated update process) and then started again - without systemctl - the systemctl status command returns an incorrect 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.

The PID file exists in this moment:

$ 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    : -

The process with this PID is running and I can connect to this TeamSpeak 3 server.

/home/teamspeak/.update.lock exists while the automated update process is running. After the update, the file is removed / deleted and does NOT exist anymore.

systemctl shows the correct status, when I kill the running service PID as systemctl restarts the service using systemd correct later.

Here is my /etc/systemd/system/ts3server.service file:

[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

Why can systemctl not return the correct status, although the TeamSpeak 3 server is started correct on a different way?


Solution 1:

You should change the Type to simple in your unit file and it will work. IIRC forking requires an explicit call of fork() method, while you start it from a bash script and there simply is no fork() call.

Solution 2:

The answer to your "why" question is that systemd is looking for the PID that it knows of (842 in your example output above), it does not track the service's own PID information. If that process is no longer running, systemd has no idea what's going on with the process. Nor can it restart it (since the ports would already be bound to by the new instance).

Probably a cleaner way to do the upgrade is

  1. Use systemctl to stop the service
  2. Perform the update, and then
  3. Use systemctl start the process.