The other day I was having problems with a syslogd dying during log rotation, at which point I was having to notice this happened (which I could tell from the emails from cron, once I checked email) and then of course I had to manually restart it. For a very long time now I've wanted a simple solution to deal with managing essential services in an rc.d world in such a way that I could automate such things. I finally remembered sysutils/monit and gave it a try. It works amazingly well and while it is extremely minimal in requirements it provides an enormous amount of features and flexibility. It was trivial to set up to monitor and restart syslogd and it works very very well. However that raised the question of how to reliably start it. I figured the best way would be to run it from init(8) so that it would be running at all times while logins are allowed, and so that init(8) could restart it should it ever die. The problem was that monit, like most programs, doesn't want arbitrary arguments on its command line, and the normal way init(8) starts a "getty" is to explicitly pass the terminal name as an additional argument. I could have named the session "-I", but that's UGLY. In the end I was unable to make it work without writing a (trivial) wrapper script, but that also seemed like a crazy requirement when all I really wanted was for init(8) to not add an extra argument if it wasn't wanted/needed. So, I decided to add a "notty" flag to ttys(5) for init(8). (line numbers are not exact) Index: init.c =================================================================== RCS file: /cvs/master/m-NetBSD/main/src/sbin/init/init.c,v retrieving revision 1.108 diff -u -u -r1.108 init.c --- init.c 22 Jun 2020 07:50:53 -0000 1.108 +++ init.c 17 Apr 2025 17:39:08 -0000 @@ -1136,7 +1145,8 @@ free(sp->se_getty); free(sp->se_getty_argv); } - (void)asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name); + (void)asprintf(&sp->se_getty, "%s %s", typ->ty_getty, + typ->ty_status & TTY_NOTTY ? "" : typ->ty_name); if (!sp->se_getty) return 0; sp->se_getty_argv = construct_argv(sp->se_getty); Of course there are other necessary (but simple and, I think, obvious) changes in lib/libc/gen/getttyent.c and the documentation. Notably in ttys(5) I wrote: notty Do not add the tty name as an argument to the command. This is useful to allow init(8) to be used to run any command that must be started when logins are allowed and which must always be running. The command will be restarted if it exits. I can now add a line like the following to /etc/ttys: monitor "/usr/pkg/bin/monit -I" - on notty and, voila! # kill -1 1 # who -a ? system boot Apr 17 14:51 . 0 term=0 exit=0 sess=0 type=boot time ? system down Apr 17 14:52 . 0 term=0 exit=0 sess=0 type=down time ? run-level m Apr 18 11:20 . 0 new=m old=T sess=0 type=run level /usr/libexec/getty - constty Apr 17 14:52 20:28 3916 term=0 exit=0 sess=1 type=login process woods - pts/0 Apr 17 14:52 00:19 3928 term=0 exit=0 sess=0 type=user process (10.0.2.146) /usr/pkg/bin/monit ? monitor Apr 18 11:20 . 20027 term=0 exit=0 sess=18 type=login process So, to me this seems like a simple but highly effective feature, and it is arguably far more elegant and simple than writing wrapper scripts. What do you all think? For those who want to do some bikeshedding, we could discuss adding a full-fledged /etc/inittab to init(8)! :-) [But not seriously -- I'm quite happy with /etc/ttys just being able to start extra processes whenever logins are allowed and using /etc/rc (with all of /etc/rc.d, etc.) to do the rest. No need to turn the world upside down just for this simple feature!] For the curious, this is the meat in my first /etc/monit/monitrc: set daemon 5 # check services at 5 second intervals set init # don't become a daemon (also called with -I) set log syslog set pidfile /var/run/monit.pid set idfile /var/run/monit.id set statefile /var/run/monit.state set mailserver localhost # primary mailserver set mail-format { from: monit%more.weird.com@localhost } set alert root%more.weird.com@localhost # receive all alerts set httpd port 2812 and use address localhost # only accept connection from localhost allow localhost # allow localhost to connect to the server and allow admin:monit # require user 'admin' with password 'monit' check process syslogd with pidfile /var/run/syslogd.pid start program = "/etc/rc.d/syslogd start" with timeout 60 seconds stop program = "/etc/rc.d/syslogd stop" group server -- Greg A. Woods <gwoods%acm.org@localhost> Kelowna, BC +1 250 762-7675 RoboHack <woods%robohack.ca@localhost> Planix, Inc. <woods%planix.com@localhost> Avoncote Farms <woods%avoncote.ca@localhost>
Attachment:
pgp52yL7gabji.pgp
Description: OpenPGP Digital Signature