Systemd: Tell if script was run by systemd or by user

Solution 1:

I agree with the other posters that you should try to rewrite the service to not call the script at all (it’s fine if your admins want to keep using it, but does the systemd service need all the 36 options?) – but it’s also not hard to detect if the script was called from systemd.

  • systemd v232 added the concept of an invocation ID of a unit, which is passed to the unit in the $INVOCATION_ID environment variable. You can check if that’s set or not.

  • systemd v231+ sets the $JOURNAL_STREAM variable for services whose stdout or stderr is connected to the journal, which seems to be the case for your service, so you could also check for that variable if you’re on systemd v231. (On v232+, $INVOCATION_ID is definitely the better choice.)

  • On older systemd versions, I don’t think there’s an environment variable that’s always present, but you can of course define one yourself by adding something like this to your service:

    Environment=LAUNCHED_BY_SYSTEMD=1
    

Solution 2:

A simple solution is to use a different script for systemd to start. The /opt/foobar/rc_script should just call systemctl start foobar.service and systemctl stop foobar.service.

Suse uses $SYSTEMD_NO_WRAP, but I don't know whether that is systemd standard or Suse specific.

if test -z "$SYSTEMD_NO_WRAP"; then
...
    /usr/bin/systemctl [start|stop] xxx.service

Solution 3:

For "Amazon Linux 2" and "Red Hat Enterprise Linux 7" I found a solution.

On these linux systems system process PID=1 is comm=systemd. The parent ID PPID of the systemd started script is 1.

There may be other linux systems where this is not the case.

#!/bin/bash
VAR_IS_SYSTEMD_SYSTEM=$( [[ $(ps -o comm -p 1 --no-headers | tr -d ' ') == "systemd" ]] && echo true )
echo VAR_IS_SYSTEMD_SYSTEM = ${VAR_IS_SYSTEMD_SYSTEM}

VAR_IS_DAEMON_SCRIPT=$( [[ "${PPID}" == "1" ]] && echo true )
echo VAR_IS_DAEMON_SCRIPT = ${VAR_IS_DAEMON_SCRIPT}

if [[ "${VAR_IS_SYSTEMD_SYSTEM}" = true ]] && [[ "${VAR_IS_DAEMON_SCRIPT}" = true ]]; then
  echo "You are a systemd Daemon Script"
else
  echo "You are a normal Script"
fi

Elements/Commands used:

  • ps -o comm -p 1 --no-headers

    Get command name of process 1

  • tr -d ' '

    Remove formatting whitespace from ps command

  • "${PPID}"

    Parent PID of bash process