Execution Environment, Identity and Exit Status
A program that works in an interactive shell can fail as a service because its identity, working directory, environment or access to files differs. A unit must describe the execution context rather than depend on the operator’s current shell.
Inspect what the manager will run
On bl06-service-lab, inspect the example created in the previous chapter:
systemctl cat bl06-demo.service
systemctl show bl06-demo.service \
-p Type -p ExecStart -p User -p DynamicUser -p WorkingDirectory \
-p MainPID -p Result -p ExecMainCode -p ExecMainStatus
systemctl status bl06-demo.service --no-pagersystemctl cat shows the fragment and drop-ins; show exposes effective properties and runtime results. The dynamic user’s actual identity can be allocated at runtime and is not a persistent human account. A PID is a point-in-time observation and can change on restart. If access is denied or the service is absent, resolve the lab setup before continuing.
ExecStart= is parsed by systemd, not automatically by an interactive shell. Shell features such as redirection, pipelines and command substitution do not work as they do in a shell unless a shell is explicitly invoked; avoid constructing shell strings from untrusted input. Use absolute executable paths, and understand the unit’s WorkingDirectory= and User=. The systemd execution manual describes execution context and environment.
Environment and privileges
Environment= and EnvironmentFile= can provide configuration. They are not a safe secret store: environment values can be exposed through manager interfaces or inherited by child processes. Prefer service credential mechanisms and appropriate file permissions for secrets. A user session’s PATH, home directory and shell initialization files should not be assumed to exist in a system service. WorkingDirectory= failure can prevent execution entirely; permissions must allow the selected service identity to traverse every parent directory and read the needed files.
Run the application with the least privilege it needs. A service account, a dynamic identity and a human user’s identity have different persistence and access properties. Dynamic identities are convenient for this stateless read-only example; persistent state requires explicitly managed directories and ownership. Do not use root merely because a permission error disappeared.
Read exit evidence
systemctl show bl06-demo.service \
-p ActiveState -p SubState -p Result -p ExecMainCode -p ExecMainStatus
sudo journalctl -u bl06-demo.service -b -n 40 --no-pagerExecMainCode and ExecMainStatus describe how the main process exited when that information is available; the unit’s Result describes the manager’s outcome. A service that never executed because setup failed has different evidence from one that executed and returned an error. A successful process exit can still be wrong for a long-running service, and active alone is not a functional check.
For the lab server, compare the process context with the unit properties and repeat the HTTP request from the previous chapter. Do not change the service identity or write to /usr/share/doc; that directory is package-managed. Later chapters address persistent service data and sandboxing.
Worked diagnosis and practice
Suppose a service reports status=200/CHDIR. Inspect the effective working directory and journal, determine whether the path exists and is accessible to the service’s identity, and fix the documented path or permissions at their owning layer. Re-run a client test after restart. If the status instead indicates an executable or permission failure, follow that evidence rather than changing unrelated paths. Record the lab unit’s effective execution context and explain why an environment variable is unsuitable for a password.