The officially official Devuan Forum!

You are not logged in.

#1 2022-02-22 16:35:21

Geoff 42
Member
Registered: 2016-12-15
Posts: 461  

Runit and background daemons

Runit is designed to work with daemons that stay in the foreground, so that the daemon may be supervised easily. Many daemons do try and run in the background but there is often an option that can be given to tell it to run in the foreground. Thus ntpd can use the -n (--nofork) option to run in the foreground.

Occasionally, there is a daemon which only runs in the background. I have found noip2 which updates my dynamic IP address. I have not found a way to tell it to run in the foreground. There are one or two things which you can do to handle this.

Runit comes with a program to change the process status (chpst).
This has a number of things it can do, such as changing the user or group it runs as.
The options which are useful here are -l & -L which can open a lock file for writing and obtain an exclusive lock on it, creating the file if necessary. -l will wait for the file to become available, while -L will fail immediately if it is not available.

The file /etc/sv/noip2/run looks like this :-

#!/bin/sh -eu
exec 2>&1

echo "executing /etc/sv/noip2/run"

chpst -L supervise/runlock /usr/local/bin/noip2 || exit 1
exec chpst -l supervise/runlock true

The echo message is logged if logging has been set up.

The daemon noip2 is run by chpst with an exclusive lock on the file /etc/sv/noip2/supervise/runlock

The second instance of chpst is ready to run the command true and waits for the lock file to become available, i.e. when noip2 stops running. When the lock file becomes available the command true will be run, which returns immediately and runit becomes aware that noip2 is no longer running and can take the appropriate actions.

But what happens if we want to stop the daemon? If

sv down noip2

is run then runit will stop the waiting chpst process, but not noip2.
After it has stopped chpst it will then look for the file finish and run it if it exists.
As we know the name of the lock file, we can find the PID of the process which has it open, using lsof, which may need installing.

apt install lsof

We can find the processes which have the lock file open :-

lsof /run/runit/supervise/noip2/runlock

COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chpst   2006   root    3w   REG   0,23        0 1738 /run/runit/supervise/noip2/runlock
noip2   2051 nobody    3w   REG   0,23        0 1738 /run/runit/supervise/noip2/runlock

We could find the PID of the daemon by looking through the output for the process run by nobody
and then printing the second field :-

PID=`lsof /run/runit/supervise/noip2/runlock | grep nobody | awk '{ print $2 }' -`

although awk can do the search as well :-

PID=`lsof /run/runit/supervise/noip2/runlock | awk '/nobody/ { print $2 }' -`

However, a study of the lsof man page shows that there are lots of options available and the -t option just prints out the PIDs

lsof -t /run/runit/supervise/noip2/runlock

2006
2051

Also, there is the -c option which can select the process of a particular command or filter out processes of certain commands with the negation ^. In this case we don't want the chpst process.

lsof -t -c ^chpst /run/runit/supervise/noip2/runlock

2051

which can be incorporated into the file /etc/sv/noip2/finish :-

#!/bin/sh
exec 2&>1

# use lsof to find the process with a lock on our file.

PID=`lsof -t -c ^chpst /run/runit/supervise/noip2/runlock`

echo "executing /etc/sv/noip2/finish. PID = $PID"

[ -z $PID ] && exit 1

# We could do something like "kill -TERM $PID", but in this case "noip2 -K $PID" works.

/usr/local/bin/noip2 -K $PID

This seems to work nicely. With run and finish set up the daemon can be started, supervised and stopped.

Offline

Board footer