# systemd ## See Also - ### [[Eutykhia Deploy#Service]] ## Resources - [Run any Executable as Systemd Service in Linux](https://abhinand05.medium.com/run-any-executable-as-systemd-service-in-linux-21298674f66f) - Great guide for beginners, explains what is going on - ([[Stack Overflow]]) [How do I run a single command at startup using systemd?](https://askubuntu.com/questions/919054/how-do-i-run-a-single-command-at-startup-using-systemd) ## Quickstart ### [Eutykhia Example Config](https://github.com/MaxFangX/Eutykhia/blob/master/tyche.service) ```ini [Unit] Description=Service for Eutykhia After=network.target [Service] Type=simple ExecStart=/home/%u/tyche/target/release/eutykhia monitor WorkingDirectory=/home/%u/tyche Restart=always RestartSec=15 KillSignal=SIGINT TimeoutStopSec=90 FinalKillSignal=SIGTERM [Install] WantedBy=multi-user.target ``` - `After=network.target` specifies the service should be started after we have an internet connection - `Type=simple` simple executable binary, restarts if it's not running anymore - `ExecStart=/home/ec2-user/tyche/target/release/eutykhia monitor` the command to run at start - `WorkingDirectory=/home/ec2-user/tyche` the working directory of the command - `Restart=always` whether to restart the service if it fails - `RestartSec=15` the delay between restarting the service if it fails - `KillSignal=SIGINT` send a 'polite' interrupt as initial attempt to stop the service - `TimeoutStopSec=90` send the send kill signal if it fails to stop on its own 90 seconds after the first stop signal - `FinalKillSignal=SIGTERM` force kill with `SIGTERM` if the service fails to stop on its own 90 seconds after the initial stop signal - `WantedBy=multi-user.target` "multi-user.target normally defines a system state where all network services are started up and the system will accept logins, but a local GUI is not started. This is the typical default system state for server systems, which might be rack-mounted headless systems in a remote server room. This is just another way of telling the service should start at run-levels 3,4 and 5." #### Other possibly helpful lines Automatically redirect the output from the service to a log file ```ini StandardOutput=syslog StandardError=syslog SyslogIdentifier=%n ``` ### Idiosyncracies #### `%u` and `%h` don't work the way you expect - `%u` is a template specifier for the user configured to run the unit. However, this usually turns out to be `root` since `systemctl` is usually invoked with `sudo`. - `%h` specifies the home directory of the user configured to run the unit. Likewise, this is usually `/root` instead of the home directory of the current (non-privileged) user (e.g. `/home/ubuntu`) ### Setting up the service Using [[bitcoind]] as the illustrative example: ![[bitcoind Quickstart#Set up reconfigure bitcoind service]] ## General ### Setting environment variables in a systemd service ```bash $ systemctl edit myservice ``` [Source](https://serverfault.com/questions/413397/how-to-set-environment-variable-in-systemd-service) ### List all services ```bash systemctl list-units --type=service # Include inactive services too systemctl list-units --type=service --all ``` ### Sending Ctrl+C to a `systemd` process #### Background: Termination signals - `SIGINT` is equivalent to Ctrl+C - `SIGTERM` is equivalent to `kill`ing a process. - "The `SIGQUIT` signal is similar to `SIGINT`, except that it’s controlled by a different key—the QUIT character, usually C-\—and produces a core dump when it terminates the process, just like a program error signal. You can think of this as a program error condition “detected” by the user." - The `SIGKILL` signal is used to cause immediate program termination. It cannot be handled or ignored, and is therefore always fatal. It is also not possible to block this signal. - This signal is usually generated only by explicit request. Since it cannot be handled, you should generate it only as a last resort, after first trying a less drastic method such as C-c or `SIGTERM`. If a process does not respond to any other termination signals, sending it a `SIGKILL` signal will almost always cause it to go away. In fact, if `SIGKILL` fails to terminate a process, that by itself constitutes an operating system bug which you should report. - The system will generate `SIGKILL` for a process itself under some unusual conditions where the program cannot possibly continue to run (even to run a signal handler). - The `SIGHUP` (“hang-up”) signal is used to report that the user’s terminal is disconnected, perhaps because a network or telephone connection was broken. #### Fantastic [[Stack Overflow]] answer here: https://unix.stackexchange.com/a/605539/488417 > By default, if you `systemctl stop` a process, systemd sends SIGTERM to the process. That process is responsible for handling the signal and shutting down gracefully. If the process does not shutdown within 90 seconds, SIGKILL will forcefully stop the process. > > There are several ways to change this default behaviour: > > - `ExecStop=`: If your process would normally shutdown via an external signal from a socket, shared-memory, touched file, you can execute a script that sends that to your process using `ExecStop=`. > - `KillSignal=`: If your process doesn't respond well to SIGTERM, you can change which signal is sent to the process using `KillSignal=`. Maybe your process responds better to SIGINT, SIGABRT, or SIGQUIT. Note that this signal should initiate the save that your program will perform. > - `TimeoutStopSec=`, This defaults to 90s, giving that time between the first `KillSignal` and `FinalKillSignal`. > - `SendSIGKILL=`: If your process does start the save, but you want to wait indefinatley, you can set this to `no` to let the service hang forever. (Play with `TimeoutStopSet` first). > - `FinalKillSignal=`: If your killsignal didn't work well and you want to followup after `TimeoutStopSet` with something other than `SIGKILL` you can set that code here.