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.