Allow other users to stop / restart simple bash daemons - use signals or what?

I have a web server where I run programs with slow startup as daemons. Sometimes they need a quick restart (or stop) when recompiling or switching to another installation.

Inspired by http://mywiki.wooledge.org/ProcessManagement , I am writing a script called daemonise.sh that looks like

 #!/bin/sh while :; do ./myprogram lotsadata.xml echo "Restarting server..." 1>&2 done 

to run the "daemon". Since I sometimes need to stop this or just restart it, I ran this script in a screen session, for example:

 $ ./daemonise.sh & DPID=$! $ screen -d 

Then, perhaps, I will recompile myprogram, install it on a new path, start a new one and want to kill the old one:

 $ screen -r $ kill $DPID $ screen -d 

This works great when I'm the only maintainer, but now I want to let someone stop / restart the program, regardless of who started it. And also to make things more complex, the daemonise.sh script actually runs about 16 programs, which makes them troublesome to kill everyone if you don't know their PID.

What would be the β€œbest way” to allow another user to stop / restart daemons?

I thought about general screen sessions, but it sounds just hacked and insecure. The best solution I came up with is to wrap the start and kill in a script that captures certain signals:

 #!/bin/bash DPID= trap './daemonise.sh & DPID=$!' USR1 trap 'kill $DPID' USR2 EXIT # Ensure trapper wrapper doesn't exit: while :; do sleep 10000 & wait $! done 

Now, if another user needs to stop the daemons, and I cannot do this, she just needs to know the pid of the wrapper and, for example, sudo kill -s USR2 $wrapperpid . (In addition, it allows you to run daemons on reboots and still kill them cleanly.)

Is there a better solution? Are there obvious problems with this solution that I don't see?

(After reading the Greg Bash Wiki, I would like to avoid any solution containing pgrep or PID files ...)

+6
source share
2 answers

I recommend init based on a PID script. Anyone who has the sudo privilege for a script will be able to start and stop server processes.

+1
source

On improving your approach: it would not be wise for your sleep command to sleep 10000 & wait $! was completed correctly if your pidwrapper script somehow exits?

Otherwise, a tattered sleep process would remain in the process table for some time.

Likewise, would it be cleaner to terminate myprogram in daemonise.sh correctly on reboot (for example, if daemonise.sh receives a TERM signal)?

You can also suppress job notifications and check for pid before killing.

 #!/bin/sh # cat daemonise.sh # cf. "How to suppress Terminated message after killing in bash?", # http://stackoverflow.com/q/81520 trap ' echo "server shut down..." 1>&2 kill $spid1 $spid2 $spid3 && wait $spid1 $spid2 $spid3 2>/dev/null exit ' TERM while :; do echo "Starting server..." 1>&2 #./myprogram lotsadata.xml sleep 100 & spid1=${!} sleep 100 & spid2=${!} sleep 100 & spid3=${!} wait echo "Restarting server..." 1>&2 done #------------------------------------------------------------ #!/bin/bash # cat pidwrapper DPID= trap ' kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null ./daemonise.sh & DPID=${!} ' USR1 trap ' kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null kill -0 $DPID 2>/dev/null && kill $DPID && wait ${DPID} 2>/dev/null ' USR2 trap ' trap - EXIT kill -0 $DPID 2>/dev/null && kill $DPID && wait ${DPID} 2>/dev/null kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null exit 0 ' EXIT # Ensure trapper wrapper does not exit: while :; do sleep 10000 & wait $! done #------------------------------------------------------------ # test { wrapperpid="`exec sh -c './pidwrapper & echo ${!}' | head -1`" echo "wrapperpid: $wrapperpid" for n in 1 2 3 4 5; do sleep 2 # start daemonise.sh kill -s USR1 $wrapperpid sleep 2 # kill daemonise.sh kill -s USR2 $wrapperpid done sleep 2 echo kill $wrapperpid kill $wrapperpid } 
+1
source

Source: https://habr.com/ru/post/909282/


All Articles