I'm writing a systemd service which can be started or stopped using systemctl commands.

However this program can also return with several return codes and I would like to handle those return codes.

For example if the service was stopped with systemctl stop <service> it should do nothing. But if it wasn't killed by systemctl and returned by itself I want to run a post script on which I could get the return code and do actions depending on its value.

Modified after @NarūnasK answer
When having systemd version >= v232 it's okay with @NarūnasK answer

However when not having the good systemd version how could it be done ?

I though about doing something like

ExecStart=/bin/sh -c '<service> -C /etc/<service_conf_file>; [ $? -eq 1 ] && { <action> }'
  • Please take a look to the edited answer.
    – NarūnasK
    Dec 14, 2017 at 12:29

1 Answer 1


ExecStopPost= should do what you want.

Additional commands that are executed after the service is stopped. This includes cases where the commands configured in ExecStop= were used, where the service does not have any ExecStop= defined, or where the service exited unexpectedly. This argument takes multiple command lines, following the same scheme as described for ExecStart=. Use of these settings is optional. Specifier and environment variable substitution is supported. Note that – unlike ExecStop= – commands specified with this setting are invoked when a service failed to start up correctly and is shut down again.

It is recommended to use this setting for clean-up operations that shall be executed even when the service failed to start up correctly. Commands configured with this setting need to be able to operate even if the service failed starting up half-way and left incompletely initialized data around. As the service's processes have been terminated already when the commands specified with this setting are executed they should not attempt to communicate with them.

Note that all commands that are configured with this setting are invoked with the result code of the service, as well as the main process' exit code and status, set in the $SERVICE_RESULT, $EXIT_CODE and $EXIT_STATUS environment variables, see systemd.exec(5) for details.

In your script you can read $EXIT_CODE or $EXIT_STATUS environment variables and take appropriate action.


You can use the following workaround with systemd < 232.


#! /bin/bash --

sleep 5

## Non standard exit code
exit 255


#! /bin/bash --


echo CODE: $CODE


# systemctl cat sample_script.service 
# /etc/systemd/system/sample_script.service
Description=My service
After=network.target rsyslog.service

ExecStart=/bin/bash -c '/tmp/sample_script || /tmp/exit_handler $?'


Status of the sample_script.service:

# systemctl status sample_script.service 
● sample_script.service - My service
   Loaded: loaded (/etc/systemd/system/sample_script.service; enabled)
   Active: inactive (dead) since Thu 2017-12-14 12:29:16 GMT; 7s ago
  Process: 16511 ExecStopPost=/tmp/exit_handler (code=exited, status=0/SUCCESS)
  Process: 16505 ExecStart=/bin/bash -c /tmp/sample_script || /tmp/exit_handler $? (code=exited, status=0/SUCCESS)
 Main PID: 16505 (code=exited, status=0/SUCCESS)

Dec 14 12:29:11 build-local systemd[1]: Started My service.
Dec 14 12:29:16 build-local bash[16505]: CODE: 255
Dec 14 12:29:16 build-local bash[16505]: SERVICE_RESULT:
Dec 14 12:29:16 build-local bash[16505]: EXIT_CODE:
Dec 14 12:29:16 build-local bash[16505]: EXIT_STATUS:
Dec 14 12:29:16 build-local exit_handler[16511]: CODE: N/A
Dec 14 12:29:16 build-local exit_handler[16511]: SERVICE_RESULT:
Dec 14 12:29:16 build-local exit_handler[16511]: EXIT_CODE:
Dec 14 12:29:16 build-local exit_handler[16511]: EXIT_STATUS:

You can see that exit_handler has been called twice. At first from bash where it has the exit code supplied to it and then as ExecStopPost= script, where positional argument of exit code was not supplied therefore it printed N/A.

  • I can call a script on exit but both variables are empty. I don't understand how to use SERVICE_RESULT. I tried both ExecStopPost=<myScript> SERVICE_RESULT="exit-code" inline and SERVICE_RESULT="exit-code" under [Unit] without success.
    – Arkaik
    Dec 13, 2017 at 15:15
  • Apparently these environment variables were introduced in systemd v232 [reference]. I have tested it on Debian9 (systemd v215) - it's like you said, all these variables turned out empty.
    – NarūnasK
    Dec 13, 2017 at 16:20
  • Indeed on my target the version is systemd v229... and it's the latest available in stable repos
    – Arkaik
    Dec 14, 2017 at 10:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .