Unstable or failing systemd services on Linux often come from missing dependency units or runtime settings that point to the wrong executable, user, or file path. A fast dependency and path review usually surfaces the real cause sooner than repeated restarts and reduces the risk of hitting start-limit lockouts.
systemd builds the final service definition from the unit file plus any drop-in overrides under /etc/systemd/system/<unit>.d/, then computes the dependency graph from directives such as Requires, Wants, and ordering rules like After and Before. The same merged configuration also controls runtime behavior—ExecStart command paths, optional EnvironmentFile entries, the User and Group the process runs as, and any working or state directories the service expects.
Some dependencies are implicit (for example mount units derived from path usage) and drop-ins can override earlier settings, so checking the effective configuration matters more than reading a single file. systemd does not execute ExecStart through a shell, so relative paths, shell built-ins, and interactive quoting assumptions can fail in a unit context. File and directory checks may require sudo privileges, and remote systems benefit from having console access available before applying changes that affect service startup.
Steps to check Linux service dependencies and runtime paths with systemctl:
- Display the effective unit file and any drop-in overrides.
$ systemctl --no-pager cat example.service # /etc/systemd/system/example.service [Unit] Description=Example API Wants=network-online.target After=network-online.target [Service] Type=simple User=svcuser Group=svcuser EnvironmentFile=-/etc/default/example ExecStart=/usr/local/bin/example-api --config /etc/example/example.conf WorkingDirectory=/var/lib/example Restart=on-failure RestartSec=1s [Install] WantedBy=multi-user.target
Replace service-name.service with the actual unit name, including suffixes like .service, .socket, or .timer.
- Extract dependency directives from the effective unit file.
$ systemctl --no-pager cat example.service | grep -E '^(Requires|Wants|BindsTo|Requisite|PartOf|After|Before)=' Wants=network-online.target After=network-online.target
- List the resolved dependency tree for the unit.
$ systemctl --no-pager list-dependencies --after --all --plain --full example.service | head -n 12 example.service -.mount -.slice blockdev@dev-disk-by\x2duuid-c7f70fb1\x2dad04\x2d47c0\x2d8aa2\x2d873cbef19d05.target system.slice systemd-journald.socket basic.target systemd-ask-password-plymouth.path plymouth-start.service keyboard-setup.service systemd-udev-trigger.service systemd-udevd-control.socket
Use --before to view reverse ordering, and --reverse to list units that pull the service in.
- Extract runtime path directives and service identity settings from the effective unit file.
$ systemctl --no-pager cat example.service | grep -E '^(ExecStart|ExecStartPre|ExecStartPost|WorkingDirectory|EnvironmentFile|User|Group|RuntimeDirectory|StateDirectory|CacheDirectory|LogsDirectory|ConfigurationDirectory|PIDFile)=' User=svcuser Group=svcuser EnvironmentFile=-/etc/default/example ExecStart=/usr/local/bin/example-api --config /etc/example/example.conf WorkingDirectory=/var/lib/example
A leading - in EnvironmentFile makes the file optional, while ExecStart must reference an absolute executable path because systemd does not invoke a shell.
- Verify that referenced executables and files exist and have expected permissions.
$ sudo ls -l /usr/local/bin/example-api /etc/example/example.conf /etc/default/example -rw-r--r-- 1 root root 23 Jan 10 06:59 /etc/default/example -rw-r--r-- 1 root root 27 Jan 10 06:59 /etc/example/example.conf -rwxr-xr-x 1 root root 607 Jan 10 07:00 /usr/local/bin/example-api
A missing ExecStart binary or an unreadable non-optional EnvironmentFile causes immediate start failure and may trigger systemd start-limit suppression (restarts blocked until the limit window resets).
- Check that referenced working or state directories exist and are owned appropriately for the configured service account.
$ sudo ls -ld /var/lib/example /var/log/example /run/example drwxr-xr-x 2 svcuser svcuser 40 Jan 10 07:08 /run/example drwxr-x--- 2 svcuser svcuser 4096 Jan 10 06:59 /var/lib/example drwxr-xr-x 2 svcuser svcuser 4096 Jan 10 06:59 /var/log/example
Paths under /run/ are often created at service start and may not exist while stopped unless RuntimeDirectory (or similar) is configured.
- Confirm that prerequisite units from the dependency chain are active.
$ systemctl is-active network-online.target systemd-journald.socket active active
List globally failed units when a prerequisite is suspected:
$ systemctl --no-pager --failed
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
