How to write runit custom stop script

I want to have a custom "stop" script runit (runsv) to execute when having to stop/restart the process. Currently it simply kills the process, then runs the "finish" script. But in my case, my process spawns dynamically child processes, so instead of simple kill, I need a "killtree" to get rid of them. How do I do that?

I know it should be done through the control options of runit but from reading the docs its not really clear to me how the stop script should be named :(

http://smarden.org/runit/runsv.8.html


From the docs

For each control character c sent to the control pipe, runsv first checks if service/control/c exists and is executable. If so, it starts service/control/c and waits for it to terminate, before interpreting the command. If the program exits with return code 0, runsv refrains from sending the service the corresponding signal. The command o is always considered as command u. On command d first service/control/t is checked, and then service/control/d. On command x first service/control/t is checked, and then service/control/x. The control of the optional log service cannot be customized.

That means you need to create a service_name/control/X, X being an executable that will run when you send the related sv command to the service, like the d command (down). If your script exits with status 0 it will not try to down the service itself.

Basically you need an executable script on /etc/sv/<service>/control/d that will do whatever you want and kill the service, clean up pids and etc.


The simple answer is to name your cleanup script "service/finish". This script is executed when "service/run" exits.

There is also a "service/control/ctrl_char interface. It allows you to perform differing actions depending on which command you send to runsv.


I had to solve this problem myself for docker. I had uwsgi server running, and it was sent the wrong signal by docker (TERM instead of INT) on stopping the container.

The idea of the control/x files is to react to a received signal. In my case i would place a t file for the terminate signal into control, since it is the file reserved for the term signal. The script should be executable.

#!/bin/bash
kill -INT `cat /tmp/project-master.pid`

The script sends an int signal to the uwsgi process, which is what I want.

If the control script is exiting without error (return code 0) the original signal will not be sent to the process.

So in my case I was able to receive the term signal and sending out a int signal to the service process instead.