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

  • 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.

  • 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 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?

    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").

    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.

License under CC-BY-SA with attribution

Content dated before 6/26/2020 9:53 AM