The "proper" way to test if a service is running in a script

systemctl has an is-active subcommand for this:

systemctl is-active --quiet service

will exit with status zero if service is active, non-zero otherwise, making it ideal for scripts:

systemctl is-active --quiet service && echo Service is running

If you omit --quiet it will also output the current status to its standard output.

As pointed out by don_crissti, some units can be active even though nothing is running to provide the service: units marked as “RemainAfterExit” are considered active if they exit successfully, the idea being that they provide a service which doesn’t need a daemon (e.g. they configure some aspect of the system). Units involving daemons will however only be active if the daemon is still running.


systemctl does have a mode suitable for scripting; use show rather than status, and add the -p / --properties and --value options to get only the output you want.

Here's an example (from an Ubuntu 17.04 system):

$ systemctl show -p SubState --value NetworkManager
running

Running (or otherwise) is a SubState. If you want to know whether a service is active, use the property ActiveState

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead

Notes from the man:

show [PATTERN...|JOB...]
           Show properties of one or more units, jobs, or the manager
           itself. If no argument is specified, properties of the
           manager will be shown. If a unit name is specified, properties
           of the unit are shown, and if a job ID is specified,
           properties of the job are shown. By default, empty properties
           are suppressed. Use --all to show those too. To select specific
           properties to show, use --property=. This command is intended
           to be used whenever computer-parsable output is required. Use
           status if you are looking for formatted human-readable output.

-p, --property=
           When showing unit/job/manager properties with the show command,
           limit display to properties specified in the argument. The
           argument should be a comma-separated list of property names,
           such as "MainPID". Unless specified, all known properties are
           shown. If specified more than once, all properties with the
           specified names are shown. Shell completion is implemented for
           property names.

--value
           When printing properties with show, only print the value, and
           skip the property name and "=".

To see available properties for a service, run (for example, for polkit)

systemctl show -a polkit

There are many properties, so if you know what you're looking for...

$ systemctl show - polkit | grep Active
ActiveState=active
ActiveEnterTimestamp=Thu 2020-07-02 07:24:40 IST
ActiveEnterTimestampMonotonic=6682102
ActiveExitTimestamp=
ActiveExitTimestampMonotonic=0

As a complement to Zanna's answer, the --value option for systemctl show has been introduced with version 230 of systemd. So it may not be available on certain distros like debian jessie.

In this case, one can emulate the option by using sed:

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running