I would like to know if a certain systemd unit exists.

This should work for:

  • any type of unit (service, target, mount, ...)
  • running, disabled or masked unit

I know I could do this:

systemctl list-unit-files | grep "^my.target"

But it feels like there has to be a better way.

Optionally, I would like to be able to run this check by just specifying my without the need to specify ".service" (like for other systemctl commands), something like

systemctl exists my
  • You could just do a status on it...
    – rogerdpack
    Sep 5 '19 at 16:31
  • systemctl status also implies .service, so doesn't pick up mounts & targets
    – Jeff Schaller
    Sep 5 '19 at 17:03
  • And status does not work on masked services I think
    – Chris Maes
    Sep 5 '19 at 17:10

I'm not aware of a native systemd way to do it, but you could (ab)use systemctl list-unit-files:

systemctl-exists() {
  [ $(systemctl list-unit-files "${1}*" | wc -l) -gt 3 ]

This creates a "testing" function that you could use like this:

systemctl-exists my && echo my exists as a systemd unit

The * suffix is there to allow systemd to match the given argument with any "type" (service, target, or mount). This function is hard-coded to the current systemctl list-unit-files output that includes at least three lines of output (when no matching units exist); more when there are matching units:

1. UNIT FILE            STATE
   (one or more matching unit files)
2. (a blank line)
3. "%d unit files listed."

Also note that the wildcard at the end could lead to false-positives if you have unit files with similar prefixes -- searching for "au" will find fool's gold with "auditd", "autofs", and others, even if you only expected the real thing "au.service". Spell out more of the service name if you know it: systemctl-exists au.service will do the right thing.

I initially thought systemctl cat would work as a filter, but it apparently assumes that the argument is a service and so does not filter appropriately for other types (e.g. target or mount).

  • thanks for the answer, but I fail to see much added value to my answer. Strange that such an option does not exist.
    – Chris Maes
    Sep 5 '19 at 15:47
  • 1
    There is at least one person who visits U&L that's more familiar with systemd than I am; if filbranden happens to see the question, I hope they can weigh in.
    – Jeff Schaller
    Sep 5 '19 at 15:48
  • 3
    systemctl cat works fine - systemctl itself tends to treat a unit without extension as having .service. Compare, e.g., systemctl cat -- foo.service &> /dev/null && echo $? and systemctl cat -- -.mount &> /dev/null && echo $?
    – muru
    Sep 5 '19 at 15:56
  • @muru, my concern was in trying to use systemctl cat dev-mqueue, for example, and have it find dev-mqueue.mount. Adding a wildcard doesn't help, and so that falls down on the "without the need to specify .service" requirement.
    – Jeff Schaller
    Sep 5 '19 at 16:01
  • But it also says, "like other systemctl commands", and in this respect it is behaving exactly like those commands. (That's to say, if cat failed, so would those.)
    – muru
    Sep 5 '19 at 16:02

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.