Scripting Complex Logic in ExecStartPre
In this lesson, you will learn how to use ExecStartPre to implement robust pre-flight checks that prevent your services from entering an error state due to missing dependencies or invalid environments.
Why Pre-flight Checks Matter
Often, a service will fail immediately after starting because a configuration file is missing, a required network mount isn't ready, or a database isn't reachable. By default, systemd might attempt to restart this failing service repeatedly, wasting resources and cluttering your logs. By inserting an ExecStartPre script, you can perform these "sanity checks" before the main process ever launches. If the script exits with a non-zero status, systemd treats it as a failure and aborts the start sequence cleanly, sparing your application the overhead of an unnecessary boot cycle.
Implementing Logic in the Unit File
You can specify multiple ExecStartPre lines, which systemd executes in order. For complex logic, it is best practice to point to a shell script.
Consider this example for a custom backup service that requires a specific external drive and a valid config file:
[Service]
# Verify the configuration file exists
ExecStartPre=/usr/bin/test -f /etc/myapp/config.json
# Verify the backup directory is mounted
ExecStartPre=/usr/bin/bash -c 'mountpoint -q /mnt/backup || exit 1'
# Run the actual application
ExecStart=/usr/local/bin/backup-manager.sh
Advanced Control
If your logic requires more complex branching—such as checking if a secondary service is active or verifying disk space—writing a dedicated script is cleaner than stuffing logic into the unit file. Remember that ExecStartPre runs as the user specified in User= (or root by default). If your script returns an exit code of 1 (or any non-zero value), systemd stops the sequence. You can also use ExecStartPre=-/path/to/script (with a leading dash) if you want to ignore the exit status of a check, though for critical pre-flight conditions, you should always allow the unit to fail to ensure the system state remains predictable.
Key Takeaway: Use ExecStartPre to perform environmental validation before launching your service; this prevents cascading failures by ensuring the system meets all necessary requirements before the main binary executes.