How Can a Program Detect If It Is Running as a Systemd Daemon

How can a program detect if it is running as a systemd daemon?

Get the parent process id and see whether that process is systemd.

Test if bash script was initiated from systemd

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.

A reliable way to detect systemd

This sounds like an XY problem to me. I can imagine two reasons why you might be caring:

  1. You want to know whether to run your program in foreground mode or daemon mode.
  2. You rely (possibly optionally) on systemd services.

Defining "daemonize" as "(double) fork and exit the parent to be reparented to init, as well as taking care of other steps such as giving up the controlling terminal, ..." (Edit: the systemd maintainers have written a handy man page: daemon(7) (not to be confused with daemon(3), which is not useful)

A traditional daemon would take a command-line option: either --daemonize (if the default is to run in the foreground) or --foreground (if the default is to daemonize). The responsibility to pass one of those flags belongs to whoever started the program (if a user) or whoever wrote the init script (which should be the packager, not you the upstream).

The trend in modern practice has changed: processes should not take care of themselves, but are run by a daemon manager, such as start-stop-daemon(8) (again, a decision of the packager).

Now that systemd is becoming ubiquitous, some of the best practices are changing. For example, it is now possible for the upstream to ship one .service file instead of each packager having to ship their own variant, and it is now completely pointless to implement the daemonization steps on your own.

For the second case, if you want to use some of systemd's services - just try to use them, and check for errors like you always should. For many applications you wouldn't yet want to make it a hard error (there should probably be some way to run your program without systemd, if only for development/testing - but this could require changing some config option, it doesn't have to be easy), but a hard dependency is becoming legitimate now.

Detect if code is running as a service

You can add the Microsoft.Extensions.Hosting.WindowsServices NuGet package and use the WindowsServiceHelpers.IsWindowsService() helper method.

For Linux you can use Microsoft.Extensions.Hosting.Systemd and the SystemdHelpers.IsSystemdService() method.

How to see if a service is running on Linux?

systemctl status name.service

check this out

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-services

Python code to check if service is running or not.?

Simply by using os.system(). You then get the return code of the execution; 0 means running, 768 stopped

>>> import os
>>> stat = os.system('service sshd status')
Redirecting to /bin/systemctl status sshd.service
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2017-10-05 09:35:14 IDT; 29s ago
Docs: man:sshd(8)
man:sshd_config(5)
Process: 620 ExecStart=/usr/sbin/sshd $OPTIONS (code=exited, status=0/SUCCESS)
Main PID: 634 (sshd)
CGroup: /system.slice/sshd.service
└─634 /usr/sbin/sshd
>>> stat
0 <-- means service is running

>>> os.system('service sshd stop')
Redirecting to /bin/systemctl stop sshd.service
0 <-- command succeeded

>>> os.system('service sshd status')
Redirecting to /bin/systemctl status sshd.service
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Thu 2017-10-05 09:41:58 IDT; 10s ago
Docs: man:sshd(8)
...
768 <-- service not running

The return code is the one returned from the execution. From the service manpage:

EXIT CODES
service calls the init script and returns the status returned by it.

So it's up to the init script executed. You can safely say any return code other than 0 means the service is not running.

You can either check if the process is running instead using:

>>> os.system('ps aux | grep sshd | grep -v grep | wc -l')
2
>>> os.system('ps aux | grep sshd123 | grep -v grep | wc -l')
0


Related Topics



Leave a reply



Submit