How can I tell if a script was called from systemd or from a user?

I created a service for an old school daemon. We just switched to systemd and some of my admin like to call the rc-script directly. This won't work very well in the case of machine reboot. Systemd won't honor the PIDFile= because the new started daemon is not part of it's cgroup for the service.

I added the service file and the rc_script. I can't differ by user id, because to use the script the user has to be foobaruser.

The stop service is now problem, because systemd will recognize this from the deleted pid file.

So how do I find out if the script was called from systemd?


Description=Foobar Service
After=syslog.target network.target

ExecStart=/opt/foobar/rc_script start
ExecStop=/opt/foobar/rc_script stop


/opt/foobar/rc_script skeleton

case $1 in
  VAR_IS_SYSTEMD=$( ... script to check if bash is run from systemd ... )
  if [ "$VAR_IS_SYSTEMD" = false ] ; then
    sudo systemctl start foobar.service
  # start service within systemd
  # stop service
  • 2
    This is really not a problem you should aim to solve; better to make a clean break. Work on developing an understanding of what systemd (and journalctl) can do and after getting over the initial hump your users will develop their muscle memory and have a better mental model of how things work. Publish a conversion cheat-sheet within your team. Aug 15, 2018 at 8:30
  • @CameronKerr I agree with you for shorter scripts. Unfortunately this script grew to 2500 lines and has 36 option for calling. SO I decided to leave it that way it is and filter out the user/other script calls.
    – notes-jj
    Aug 17, 2018 at 15:54
  • Just get rid of the old rc script and put the appropriate logic to start the service in the systemd unit. Aug 17, 2018 at 17:47
  • 1
    I ran into a very similar problem and came up with a "parent PID" solution; after using those words in a search, I found this Q/A. To tie everything together, I wrote up a Q/A on the U&L site at unix.stackexchange.com/q/622902/117549; it has generated some additional ideas that visitors to this Q/A might find useful. Dec 6, 2020 at 15:51

3 Answers 3


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:

  • The latter option is the one that'll work on RHEL7 (systemd 219), which I need to support for another two years. Lowest common denominator, and I don't want to write it two different ways. Thanks for the idea! Although I'd go =true so I can just script if ${LAUNCHED_BY_SYSTEMD}; then ...
    – Rich
    Apr 14 at 2:39

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
  • Unfortunately this does not work for "Amazon Linux 2" nor "Red Hat Enterprise Linux 7"
    – notes-jj
    Aug 17, 2018 at 15:20

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.

VAR_IS_SYSTEMD_SYSTEM=$( [[ $(ps -o comm -p 1 --no-headers | tr -d ' ') == "systemd" ]] && echo true )

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

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

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

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.