Why is the Systemd unit loaded, but inactive (dead)

systemd

I'm trying to set up Graphite on my server. I can start the Carbon Cache daemon no problem with sudo /opt/graphite/bin/carbon-cache.py start, but I'm struggling to run it as a Systemd unit.

Here's what I have in my service file, graphite.service:

[Unit]
Description=Carbon for Graphite

[Service]
ExecStart=/opt/graphite/bin/carbon-cache.py start

[Install]
WantedBy=multi-user.target

But when I start the unit I get the following status:

$ systemctl status graphite.service            
* graphite.service - Carbon for Graphite
   Loaded: loaded (/etc/systemd/system/graphite.service; enabled)
   Active: inactive (dead) since Fri 2014-06-13 18:44:11 UTC; 2s ago
  Process: 4525 ExecStart=/opt/graphite/bin/carbon-cache.py start (code=exited, status=0/SUCCESS)
 Main PID: 4525 (code=exited, status=0/SUCCESS)

Jun 13 18:44:11 MEADOW systemd[1]: Started Carbon for Graphite.

Journalctl yields no more information.

How should I interpret and debug units with a status of "inactive (dead)…(code=exited, status=0/SUCCESS)"? I've seen failed units before, but this one is successfully loaded yet not running and I don't know what that means.

Best Answer

Per jasonwryan's comment, while the default Type=simple works for many Systemd service files, it does not work when the script in ExecStart launches another process and completes, as is the case with graphite's carbon-cache.py. In these cases you need to explicitly specify Type=forking in the [Service] section so that Systemd knows to look at the spawned process rather than the initial one.

As explained in man systemd.service:

If set to forking, it is expected that the process configured with ExecStart= will call fork() as part of its start-up. The parent process is expected to exit when start-up is complete and all communication channels are set up. The child continues to run as the main daemon process. This is the behavior of traditional UNIX daemons. If this setting is used, it is recommended to also use the PIDFile= option, so that systemd can identify the main process of the daemon. systemd will proceed with starting follow-up units as soon as the parent process exits.

Graphite-Specific Answer

While the above solved my Systemd issue, I quickly ran into graphite-specific issues (with Twisted) and ended up going back to the default Type.

Graphite < 0.9.12

In previous versions of Graphite one can only avoid forking by using the --debug option:

[Service]
ExecStart=/opt/graphite/bin/carbon-cache.py --debug start

Graphite >= 0.9.13

In this pull request a --no-daemon option was merged:

[Service]
ExecStart=/opt/graphite/bin/carbon-cache.py --no-daemon start