Automating things without systemd
This year I ran into a peculiar problem: how does one daemonze a process without using any systemd
related utilities (user services also won’t work because SSH sessions are not considered real sessions); the reasoning behind this bizarre problem is the way the VPS owner shares it’s usage between other people (letting people sudo
around doesn’t look like a good idea)
The obvious choice in that case is to write a wrapper script which would make sure a specific process (or a screen session, I will touch on that next) is always running, and if it isn’t, the wrapper will launch it. This script should be executed at a fixed interval by putting it inside your crontab
Using nohup
The nohup
utility allows you to force a process into the background without holding on to your current session. This is the simplest method of daemonizing stuff which comes at a cost of not being able to read/write process input/output streams without some dark pipe file magic.
Example script:
#!/bin/bash
processes=$(ps -o cmd)
if echo ${processes} | grep -wq PROCNAME; then exit 0; fi
nohup /usr/bin/PROCNAME ARGS > /dev/null 2>&1 &
exit 0
A pesky thing with this specific script is the need to strictly match process names because the wrapper script lists all the user processes including the wrapper script itself; to mitigate this, the
-w
key is used when grep-ing which makes the utility to only produce exact matches.
A cron job is then created to run the wrapper script at a set fixed time interval (in my case it’s every 5 minutes, it can be different); just consider your environment’s PID limit and choose the interval accordingly (in this specific case the VPS was grinding to a screeching halt when PID values exceeded 40000):
*/5 * * * * /usr/local/bin/SCRIPTNAME
Using screen
If the daemonized process needs to have an interactive standard input, using GNU screen is the best choice. GNU screen creates a detached virtual terminal session which can be then forced into the background without affecting your current session; you can also then re-attach it to your session with a simple command and detach it back with a key combination.
Example: I run a Minecraft server on the same exact VPS. The wrapper script is much more complicated and is designed to resemble a classic sysvinit
script that one would place in the rc.d
directory to be then called by the init process. It’s too big to paste it in the blog post so have a clickable link.
Let’s quickly go through all the stuff the script does:
- Passing
watch
as an argument makes the script check if a specific named screen session is running and if there isn’t one, the script will create one; - Passing
start
orrestart
as an argument makes the script ensure there is no specific named session running, and then the script will create a new session; - Passing
stuff
puts a single line followed by a LF character into the session’s standard input stream; if there isn’t a session, the script prints and error; - Passing
stop
clobbers the active session, if there is one;
Cron job entries for the server look like this:
*/5 * * * * /home/und/nrmc/service.sh watch
30 19 * * * /home/und/nrmc/service.sh stuff broadcast Restarting in 30 minutes
45 19 * * * /home/und/nrmc/service.sh stuff broadcast Restarting in 15 minutes
55 19 * * * /home/und/nrmc/service.sh stuff broadcast Restarting in 5 minutes
55 19 * * * /home/und/nrmc/service.sh stuff save-all
00 20 * * * /home/und/nrmc/service.sh restart
And, as evident by the screenshots, the approach works: