3

I have a systemd service to run a monitoring bash script which is started by a systemd timer. I've used Type=oneshot which seems the most appropriate. However, sometimes the script needs to call another program, which happens to fork. Once it does that, the script is done and exits, but once the script exits, systemd will kill all the remaining child processes.

I could use KillMode=process to prevent that, but then there's a risk that in other paths through the script other processes (that don't fork) could remain running after exit.

What's the best way to deal with this?

By the way, the forking program is dhcpcd, but I think the question applies generally. dhcpcd was originally started by ifplugd and this script is a failsafe just in case the system ends up in a state where dhcpcd isn't running anymore.

1 Answer 1

1

Processes get killed because they belong to a control group (cgroup) associated with the service, e.g. here (for system service):

/sys/fs/cgroup/systemd/system.slice/your-service.service

To move a process out of the cgroup, assign it to another cgroup. The "parent cgroup" seems right. For a system service it's like this:

echo <PID> > /sys/fs/cgroup/systemd/system.slice/tasks
# or even to the general systemd cgroup
echo <PID> > /sys/fs/cgroup/systemd/tasks

To run some command in this cgroup from the very beginning, run a shell that assigns itself to the cgroup and then execs to the actual command:

sh -c 'echo "$$" > /sys/fs/cgroup/systemd/tasks; exec /the/forking/program'

/the/forking/program will replace the shell, already in the new cgroup. When it forks, the forked instance will find itself in the new cgroup. When the main script exits, systemd will kill processes in the cgroup associated with the service, but the program in question will not be among them.

Maybe there is a more proper way to solve your problem, with unit files or something. I don't know it though.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .