Search code examples
bashsystemd

Test if bash script was initiated from systemd


As a Unix sysadmin, we experience issues with others (E.g. DBAs) starting/stopping services by interactively running scripts. This means systemd has no knowledge of the state of a service. To prevent this, I insert a conditional in the scripts like this:

# The systemd unit creates a ORACLE_SYSTEMD_UNIT environment variable.  If this
# isn't set (i.e. Not running through systemd) then abort.
if [ "${ORACLE_SYSTEMD_UNIT:+set}" == "" ]; then
    logmsg "Not initiated through systemd.  Aborting"
    exit 2
fi

Can anyone suggest a cleaner method, or perhaps an Environment variable that is automatically set by the systemd unit activation?


Solution

  • As pointed out in the comments, you can check the command name of the parent process. In bash the process id of the parent process is stored in $PPID. The command name for a given pid can be obtained by ps. This only works if your script is running directly under systemd.

    if [ "$(ps -o comm= $PPID)" != systemd ]; then
        echo "Not running under systemd"
    fi
    

    If you also want to check the parents of the parents and so on, iterate/recurse. The parent of any pid can be obtained by ps too.

    runsUnderSystemd() {
        pid="${1-$$}"
        [ "$pid" = 0 ] && return 1
        [ "$(ps -o comm= "$pid")" = systemd ] ||
        runsUnderSystemd "$(ps -o ppid= "$pid" | tr -d ' ')"
    }
    if ! runsUnderSystemd; then
        echo "Not running under systemd"
    fi
    

    With pstree this can be shortend to

    if ! pstree -s $PPID | grep -Fwq systemd; then
        echo "Not running under systemd"
    fi
    

    Alternatively, you can set an environment variable in your .service file for systemd ...

    [Service]
    Environment="STARTED_BY_SYSTEMD=yes"
    

    ... which can then be checked in all children of the started service

    if [ "$STARTED_BY_SYSTEMD" != yes ]; then
       echo "Not running under systemd"
    fi
    

    Please note that both approaches are just safeguards against mistakes. An attacker could fake or hide systemd in either way.