Monitoring processes with mon
mon is an extremely small, simple, and light-weight alternative to monit for monitoring processes. Monit’s approach of using a DSL is at times inflexible and often annoying. Mon’s approach is to monitor only a single process, monitoring of several require a mon instance per process, however reducing single points of failure.
This may sound like it’s a lot of work to manage, but I promise you it’s not! There’s another tool for this called mongroup(1) to tie them together.
Monitoring a single process
Mon instances weigh in at about 400kb per process, so you don’t have to worry about spawning a bunch of them. The simplest use of mon accepts a command to execute, and keep alive:
$ mon "echo hello; sleep 5"
Mon will execute the command with /bin/sh -c, so brace expansion and other shell goodies
are completely fine. Once the sub process exits, mon will bring it back to life. By default
mon logs to stdout:
mon : child 94136
mon : sh -c "echo hey; sleep 5"
hey
mon : last restart less than one second ago
mon : 10 attempts remaining
mon : child 94138
mon : sh -c "echo hey; sleep 5"
hey
mon : last restart 5 seconds ago
mon : 9 attempts remaining
mon : child 94140
mon : sh -c "echo hey; sleep 5"
hey
Mon will continue to execute the command until mon itself is signalled with SIGQUIT or SIGTERM at which point it will signal the child using the same signal, and gracefully exit.
When a process continues to fail upon restart, cyclic spawning will be detected by mon, it will
then exit and log a warning. By default 10 restart attempts within 60 seconds are allowed,
however you may tweak this value with --attempts <n>.
Failure alerts
Mon provides two facilities for notification. The first is the --on-restart <cmd> flag,
which mon will invoke upon any restart. This is useful for emailing administrators
the tail of a log file, notifying your team via IRC, etcetera.
The second, and more crucial facility is the --on-error <cmd> flag, which is invoked
only when a cyclic restart is detected, and mon has bailed out. Administrators should
be notified immediately as the process is completely down.
Daemonization
Mon’s --daemonize flag may be used to background the process and disassociate with the terminal,
at this point stdio will be redirected to the log file specified by --log, otherwise
defaulting as “./mon.log”, typically this looks something like:
$ mon -d -l /var/log/app.log "node app.js"
Monitoring multiple processes with mongroup
Using mon with several flags is obviously not something you’d want to be typing all the time, but part of the benefit of using mon is that shell scripts become your DSL. If you’re not interested in doing this yourself but have several processes to manage I recommend checking out a project by jgallen23 called mongroup(1). I’ve forked the project to add some goodies, until merged you can find them here.
Mongroup uses a simple configuration file, defaulting to the name ./mongroup.conf,
which simply lists out the pids and files directories, as well as
one or more processes to spawn:
pids = /var/run
logs = /var/log
web1 = node server 3000
web2 = node server 3001
web3 = node server 3002
web4 = node server 3003
redis = redis-server
Mongroup ships with typical init-style commands start, stop, restart, status and so on,
without a lot of the boilerplate associated with writing init scripts.
Launching processes
To check the status of your monitoring group, simply invoke mongroup status, or mongroup,
as it’s the default sub-command. You’ll see a list of process names, pids, and the status itself:

Firing up the entire suite of processes takes only a single command, mongroup start:

Checking the status again will show the process uptime:

You may also start, stop, or restart single processes at a time via:
$ mongroup stop [name]
$ mongroup start [name]
$ mongroup restart [name]

Since mongroup is working-directory sensitive unless the --config <file> flag
is specified, I recommend adding a small snippet to your shell profile similar
to the following:
procs() {
(cd ~ && mongroup $@)
}
If you’re super paranoid you can monitor mon with mon:
$ mon "mon 'node app'"
That’s all for now!
EDIT: changes to mongroup(1) have been merged! https://github.com/jgallen23/mongroup