171

My problem:

I'm writing a bash script and in it I'd like to check if a given service is running.

I know how to do this manually, with $ service [service_name] status.

But (especially since the move to systemd) that prints a whole bunch of text that's a little messy to parse. I assumed there's a command made for scripts with simple output or a return value I can check.

But Googling around only yields a ton of "Oh, just ps aux | grep -v grep | grep [service_name]" results. That can't be the best practice, is it? What if another instance of that command is running, but not one started by the SysV init script?

Or should I just shut up and get my hands dirty with a little pgrep?

  • initd -> respawn | systemd -> Restart=always. Details in man pages. – schweik Feb 21 '20 at 20:00

11 Answers 11

256

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.

  • Careful about oneshot services. They are only inactive or activating and both systemctl status and systemctl is-active exit with 3. (as of systemd-241) Workaround: systemctl show service | grep -qx ActiveStatus=activating – Alois Mahdal Jul 16 '19 at 19:51
  • @Alois I’m wondering what kind of scenarios you’ve encountered where you’d want to consider a oneshot service to be active; do you have an example? – Stephen Kitt Jul 20 '19 at 22:09
  • Sure, @StephenKitt. Tool foo does something to system involving reboot and uses a one-shot service, say, foo_cleanup at the next boot to clean things up. I'm testing this (my script is also scheduled as a service) and want to collect errors afterwards, but when is afterwards (vsauce music)? Well one of the criteria is that foo_cleanup has finished ("stopped being active"). – Alois Mahdal Aug 4 '19 at 16:18
  • It might be worth pointing out that 'is-failed' is also an option, and is useful if you need to perform an action based on a service not started. – Phill Healey Sep 6 '19 at 16:10
  • Note: for webmin the only working command is: service webmin status. systemctl won't work – Hardoman Aug 18 '20 at 15:48
55

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
  • 3
    +1 for sophisticated answer . kindly specify the distros which will accept --version option with systemctl. – S.K. Venkat Apr 26 '18 at 11:31
  • 1
    On Raspbian I used a service which would break sometimes. Instead of "active (running)" its status would be "active (exited)". "systemctl is-active" would not differentiate. This answer gave me distinctions I needed: running / exited / dead – Pila May 31 '20 at 18:25
  • Where can I get the list of available properties? – Lenin Raj Rajasekaran Jul 2 '20 at 4:59
  • 1
    @LeninRajRajasekaran I edited to add how to see this at the end of the answer - does this help you? – Zanna Jul 2 '20 at 9:25
  • 1
    @Zanna thanks, I have just did "service $serviceName status | grep Active" to get the full line of status. Nice to meet someone from my hometown 🙏 – Lenin Raj Rajasekaran Jul 2 '20 at 22:21
17

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
  • 2
    +1 for pointed out the --value intro version & distro which will not work. – S.K. Venkat Apr 26 '18 at 11:29
10

i find this useful for command line execution or if you are making scripts.

Copied from @StephenKitt

This will check if the service is down and perform service restart

systemctl is-active --quiet <service name> || <service name> restart

the || there checks if the return value from systemctl is non-zero meaning if it's not active as explained by the author.

  • You could also use `is-failed´ to test if a restart is needed. It seems a bit more intuitive for restarting a failed service. – Phill Healey Sep 6 '19 at 16:14
  • yes, but for me.. i wanted to practice myself and assume everything is running when it is not. so i can go things verify other stuffs with it. simply if you just want to check if it's not running, then 'is-failed' is a rightful choice. :) – asterisk Sep 8 '19 at 2:02
  • I think Phil's point is that using is-active means that the script will restart the service even if it was stopped manually, which could cause some confusion. – Steen Schütt Jan 21 '20 at 10:35
  • I put this into a cron job, and added logging: systemctl is-active --quiet <service name> || (echo '…' >> log.txt && systemctl restart <service name>). – Manngo Nov 27 '20 at 1:46
6


I am too late to the party , however using systemctl is-active along with && and || to this in script wont be the case all the time. The below is one I used for tomcat but can use it in method taking arguments and pass service name as arguments if u have to check multiple services but its out of scope here.

STATUS="$(systemctl is-active tomcat.service)"
if [ "${STATUS}" = "active" ]; then
    echo "Execute your tasks ....."
else 
    echo " Service not running.... so exiting "  
    exit 1  
fi

This is how I made use of.... Just sharing mine.

and for the simplicity and easy stuffs, follow others explained here :

systemctl -q is-active tomcat.service  && \
echo "Tomcat Runnung" || \
echo "Service is not running at all "
  • 1
    How is that better than simply if systemctl is-active --quiet tomcat.service? Also, [[ isn't standard shell. – Toby Speight Jun 13 '19 at 17:55
  • @TobySpeight You need to read my post a bit more as I mentioned in my post "This is how I made use of.... Just sharing mine." I never said, its a standard shell usage, if u make it single bracket, it will become then but thats out of scope here. Moreover I below mention easy single line usage to do it using && and ||. – SAGAR Nair Jun 19 '19 at 9:34
3

There are many answers using systemctl.

You have other options as well (where $? comes handy):

  • Using pidof command: suppose I am trying to find if redis-server is running. First issue pidof redis-server and then check the value of $? You will find 0 if it was running; non-zero otherwise.
  • Service specific solution: If the service provides a way to check if the service is running, you may use that. For the redis-service example, if the service is running, we will get a PONG response for redis-cli ping command. After issuing redis-cli ping, I'd check $? and if it's 0 then the service is running.
  • 3
    systemctl seems better in general, but in Windows Subsystem for Linux (v1), that won't work. +1 for this, which works well enough for me in WSL. If you don't want to use $?, you could also put, e.g., pidof cron in the test directly or do cron_pid=$(pidof cron) and use it later. The output is an empty string if the service isn't running, so one can test for it like if [ -z $cron_pid ]; then dosomething; fi – Nathan Jan 25 '20 at 15:00
2

Instead of using the sed command like in the answer of Oxmel, it is enough to use cut -d'=' -f 2 for all kind of properties queried:

for example:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running
  • That's great but you really need to give some explanation as to what those commands do. – Phill Healey Sep 6 '19 at 16:12
0

Also works for a non-systemd OS.

What about ps -C service-name? check $? for answer. If 0 it's running, if 1, it's not running.

Example:

ps -C privoxy && echo running

The quiet version:

ps -C privoxy 1>/dev/null && echo running

Caveat:

I noticed that service-names longer than 14 characters can give a false positive.

Also, see comment by ''Nick S''.

Example:

Correctly shows running:

$ ps -C notification-daemon
  PID TTY          TIME CMD
 7418 ?        00:00:04 notification-da

Incorrectly shows running:

$ ps -C notification-daemon-fake
  PID TTY          TIME CMD
 7418 ?        00:00:04 notification-da

Correctly shows not running because less that 14 characters:

$ ps -C notification
  PID TTY          TIME CMD

I got this answer from here.

  • Good to know about the -C option to ps. But this will false positive if another instance of the command is running, but not as a service, as I mentioned in my question. – Nick S Feb 13 '20 at 14:27
  • 3
    I didn't know that. I just tested it to verify and you are correct. So, this is not a good solution. – ajnabi Feb 21 '20 at 19:19
0

this is for init.d system

if service is not running then start service:

service mysql status > /dev/null ||     service mysql start &
service ssh status > /dev/null ||     service ssh start &
service php7.4-fpm status > /dev/null ||     service php7.4-fpm start &
service redis-server status > /dev/null ||     service redis-server start &
service nginx status > /dev/null ||     service nginx start  &
service cron status > /dev/null ||     service cron start &

when a program exits it returns also an error id, a signed byte. on exit without problems, the value is usually 0. on exit because of errors, the value is usually error id or frequently -1.

this value is frequently used for command integration like the numeric status id of the printed program output.

to use it with command chaining the are two options && and ||

the || checks if the exit return value is not a zero, then it runes the chained command

instead of || it impossible to write &&

the && checks if the exit return value is a zero, then it runes the chained command

similar to @asterisk answer on this page (for systemd) https://unix.stackexchange.com/a/500336/156304

-1

Have just found this great little script:

#!/bin/bash
service=replace_me_with_a_valid_service

if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
  echo "$service is running!!!"
else
  /etc/init.d/$service start
fi

Source

  • 2
    Not all services have an executable of the same name, and any user could be running a command that accidentally matches - this is a recipe for disaster. – Toby Speight Jun 13 '19 at 17:54
  • It looks like you want to make the service restarted, if it dies. In the time of init the keyword was respawn in the /etc/inittab. Now, with systemd you have to configure the service in the /etc/systemd/system/multi-user.target.wants/mydaemon.service, by simply add a row with: Restart=always. – schweik Feb 21 '20 at 19:56
-1

Below script I directly took it from Shell Script to Check Service Status article and did a small change to figure out whether the given service installed on the system.

Let's take service as Docker and save below script as check_service.sh.

#!/bin/bash

if [ "$#" = 0 ]; then
  echo "Usage $0 "
  exit 0
fi

service=$1
is_running=$(ps aux | grep -v grep | grep -v "$0" | grep $service | wc -l | awk '{print $1}')

if [ $is_running != "0" ]; then
  echo "Service $service is running"
else
  initd=$(ls /etc/init.d/ | grep $service | wc -l | awk '{ print $1 }')

  if [ $initd = "1" ]; then
    startup=$(ls /etc/init.d/ | grep $service)
    echo -n "Found startap script /etc/init.d/${startup}. Start it? Y/n ? "
    read answer

    if [ $answer = "y" -o $answer = "Y" ]; then
      echo "Starting service..."
      /etc/init.d/${startup} start
    fi
  else
    echo "Service $service not yet installed"
  fi
fi
  1. run the script when the service is up.
wasdkiller@kushan:~$ sudo service docker status
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-09-22 14:30:59 +0530; 6min ago
     Docs: https://docs.docker.com
 Main PID: 25220 (dockerd)
    Tasks: 17
   CGroup: /system.slice/docker.service
           └─25220 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033698487+05:30" level=warning msg="Your kernel does not support cgroup rt runtime"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033703758+05:30" level=warning msg="Your kernel does not support cgroup blkio weight"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033707702+05:30" level=warning msg="Your kernel does not support cgroup blkio weight_device"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033812954+05:30" level=info msg="Loading containers: start."
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.101347726+05:30" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to 
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.130162694+05:30" level=info msg="Loading containers: done."
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172380859+05:30" level=info msg="Docker daemon" commit=48a66213fe graphdriver(s)=overlay2 version=19.03.12
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172860484+05:30" level=info msg="Daemon has completed initialization"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.228633124+05:30" level=info msg="API listen on /var/run/docker.sock"
සැප් 22 14:30:59 kushan systemd[1]: Started Docker Application Container Engine.
lines 1-19/19 (END)
wasdkiller@kushan:~$
wasdkiller@kushan:~$
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ source check_service.sh docker
Service docker is running
wasdkiller@kushan:~$
  1. run the script when the service is down.
wasdkiller@kushan:~$ sudo service docker stop
wasdkiller@kushan:~$ sudo service docker status
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Tue 2020-09-22 14:41:00 +0530; 3s ago
     Docs: https://docs.docker.com
  Process: 25220 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=0/SUCCESS)
 Main PID: 25220 (code=exited, status=0/SUCCESS)

සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.130162694+05:30" level=info msg="Loading containers: done."
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172380859+05:30" level=info msg="Docker daemon" commit=48a66213fe graphdriver(s)=overlay2 version=19.03.12
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172860484+05:30" level=info msg="Daemon has completed initialization"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.228633124+05:30" level=info msg="API listen on /var/run/docker.sock"
සැප් 22 14:30:59 kushan systemd[1]: Started Docker Application Container Engine.
සැප් 22 14:41:00 kushan systemd[1]: Stopping Docker Application Container Engine...
සැප් 22 14:41:00 kushan dockerd[25220]: time="2020-09-22T14:41:00.691599535+05:30" level=info msg="Processing signal 'terminated'"
සැප් 22 14:41:00 kushan dockerd[25220]: time="2020-09-22T14:41:00.692925147+05:30" level=info msg="stopping event stream following graceful shutdown" error="<nil>" module=libcontainerd namespace=moby
සැප් 22 14:41:00 kushan dockerd[25220]: time="2020-09-22T14:41:00.693778800+05:30" level=info msg="Daemon shutdown complete"
සැප් 22 14:41:00 kushan systemd[1]: Stopped Docker Application Container Engine.
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ source check_service.sh docker
Found startap script /etc/init.d/docker. Start it? Y/n ? y
Starting service...
[ ok ] Starting docker (via systemctl): docker.service.
wasdkiller@kushan:~$ 
  1. run the script when the service is not yet installed in the system.
wasdkiller@kushan:~$ sudo service docker123 status
Unit docker123.service could not be found.
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ source check_service.sh docker123
Service docker123 not yet installed
wasdkiller@kushan:~$
  • can I know why I get down vote for this answer? – Kushan Gunasekera Sep 22 '20 at 10:37
  • 1
    this looks like a useful script, but the way it checks whether the service is running is the ps aux | grep -v grep method I mentioned in my question. From the other answers, it seems that there are simpler and better ways to do this (systemctl is-active and systemctl show). Thanks for the script, but if you're wondering why the downvotes, that's probably it. Make sure to read the question and other answers carefully before answering. – Nick S Sep 22 '20 at 19:34
  • 1
    Thank you very much @NickS, actually I had to capture whether the service is installed. So systemctl is-active docker and systemctl is-active docker123 both give the same answer as inactive. In my case I had to run the service if it's in stop state or it's not yet installed then I had to install it and run. Anyway thanks again @NickS. Got lot of knowledge from this answer thanks to you. Sure I'll check the question and answers next time. – Kushan Gunasekera Sep 22 '20 at 23:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.