patch for yanny

Patrick Weemeeuw (Patrick.Weemeeuw@kulnet.KULeuven.ac.be)
Mon, 8 May 1995 08:49:36 +0200

This patch for yanny (relative to the 1.99.3 scotty distribution)
adds the following functionality:

- yanny can now monitor daemons that fork (i.e. the daemon has not
the Process ID returned by the fork), provided that the daemon stores
its Process ID as the first line in a file (this file must then be
specified with the -p option)

- smarter option processing (don't get confused by options for the process
to be started).

Yanny now monitors named, sendmail, syslogd and httpd on our systems.

Patrick.

----------------------------------------------------------------------
bash$ diff -u yanny.orig yanny
--- yanny.orig Tue May 31 15:15:02 1994
+++ yanny Thu Apr 20 15:09:23 1995
@@ -34,6 +34,13 @@
## yanny rpc.statd & echo -n ' statd'
## fi
##
+## Optionally, one can also specify the name of a pid-file where
+## the daemon stores its process id; e.g.:
+##
+## if [ -f /usr/local/etc/in.named -a -f /etc/named.boot ]; then
+## yanny -p /etc/named.pid /usr/local/etc/in.named
+## echo -n ' named(local)'
+## fi
##

##
@@ -127,7 +134,7 @@

if {[info exists daemons]} {
foreach pid [array names daemons] {
- puts $fh "$pid:[lindex $daemons($pid) 0]:[join [lrange $daemons($pid) 1 end]]"
+ puts $fh "$pid:[lindex $daemons($pid) 0]:[lindex $daemons($pid) 1]:[join [lrange $daemons($pid) 2 end]]"
}
}

@@ -147,13 +154,13 @@
## Restart a daemon.
##

-proc restart {cmd} {
+proc restart { pidfname cmd} {
global daemons
if {$cmd == ""} return
write_logger "restarting $cmd"
set pid [eval exec $cmd &]
set pname [file tail [lindex $cmd 0]]
- set daemons($pid) "$pname $cmd"
+ set daemons($pid) "$pname $pidfname $cmd"
}

##
@@ -161,7 +168,7 @@
##

proc check_daemon {fname} {
- global daemons processes
+ global daemons processes debug

if {[read_daemons $fname] == 0} return

@@ -169,15 +176,19 @@

foreach pid [array names daemons] {
set name [lindex $daemons($pid) 0]
+ set pid [update_pid $pid]
+ if {$debug} {
+ puts "checking $name $pid"
+ }
if {![info exists processes($pid)]} {
write_logger "$name ($pid) gone away"
- restart [join [lindex $daemons($pid) 1]]
+ restart [lindex $daemons($pid) 1] [join [lindex $daemons($pid) 2]]
unset daemons($pid)
continue
}
if {![regexp $name $processes($pid)]} {
write_logger "$name ($pid) gone away (pid recycled)"
- restart [join [lindex $daemons($pid) 1]]
+ restart [lindex $daemons($pid) 1] [join [lindex $daemons($pid) 2]]
unset daemons($pid)
}
}
@@ -190,9 +201,9 @@
## Start it from here and save its pid.
##

-proc add_daemon {fname cmd} {
+proc add_daemon {fname pidfname cmd} {
read_daemons $fname
- restart $cmd
+ restart $pidfname $cmd
write_daemons $fname
}

@@ -210,6 +221,7 @@

foreach pid [array names daemons] {
if {[regexp $reg $daemons($pid)]} {
+ set pid [update_pid $pid]
puts "removing $pid $daemons($pid)"
exec /bin/kill $pid
unset daemons($pid)
@@ -220,42 +232,98 @@
}

##
+## If the daemon has a pidfile, check whether the pid is still accurate.
+## If not, return the new pid, and update the daemons array.
+##
+
+proc update_pid {pid} {
+ global daemons
+
+ set pid_fname [lindex $daemons($pid) 1]
+ if { [string compare $pid_fname /dev/null] } {
+ set newpid [read_pid $pid_fname]
+ if {$newpid != $pid} {
+ if {[info exists daemons($newpid)]} {
+ ## if $newpid is already in use by another daemon,
+ ## we lost track ==> give up.
+ ## (this is rather unlikely).
+ puts stderr "yanny: lost track of process ids ($pid $newpid)"
+ write_logger "lost track of process ids ($pid $newpid)"
+ exit
+ }
+ set daemons($newpid) $daemons($pid)
+ unset daemons($pid)
+ set pid $newpid
+ }
+ }
+ return $pid
+}
+
+##
+## Extract the process ID from the pid-file
+##
+
+proc read_pid {fname} {
+
+ if {![file exists $fname] || ![file readable $fname]} {
+ puts stderr "yanny: unable to open $fname"
+ exit
+ }
+
+ set fh [open $fname]
+ gets $fh line
+ if {![regexp {^[0-9]+$} $line]} {
+ puts stderr "yanny: unexpected format in $fname: $line"
+ write_logger "unexpected format in $fname: $line"
+ }
+ close $fh
+ return $line
+}
+
+##
## The main program. Check for the -y option and decide if we
## add a new daemon or if we check the actual listing.
##

set fname /etc/yanny.conf
+set pidfname "/dev/null"

set uniq 0
set kill 0
+set debug 0

set newargv ""
-foreach arg $argv {
+set parsing_options 1
+while {([llength $argv] > 0) && $parsing_options} {
+ set arg [lindex $argv 0]
+ set argv [lrange $argv 1 end]
if {[string index $arg 0] == "-"} {
switch -- $arg {
- "-y" { lappend newargv $arg }
- "-u" { incr argc -1; set uniq 1 }
- "-k" { incr argc -1; set kill 1 }
+ "-d" { set debug 1 }
+ "-y" { set fname [lindex $argv 0]
+ set argv [lrange $argv 1 end]
+ }
+ "-p" { set pidfname [lindex $argv 0]
+ set argv [lrange $argv 1 end]
+ }
+ "-u" { set uniq 1 }
+ "-k" { set kill 1 }
+ "--" { set parsing_options 0 }
}
} else {
+ set parsing_options 0
lappend newargv $arg
}
}
-set argv $newargv
-
-if {$argc > 1 && [lindex $argv 0] == "-y"} {
- set fname [lindex $argv 1]
- set argv [lrange $argv 2 end]
- incr argc -2
-}
+set argv [concat $newargv $argv]

-if {$argc == 0} {
+if {[llength $argv] == 0} {
check_daemon $fname
} else {
if {$kill} {
kill_daemon $fname [join $argv]
} else {
- add_daemon $fname [join $argv]
+ add_daemon $fname $pidfname [join $argv]
}
}

bash$ diff -u yanny.8.orig yanny.8
--- yanny.8.orig Mon Jan 10 19:45:04 1994
+++ yanny.8 Fri Apr 21 13:34:38 1995
@@ -1,15 +1,23 @@
-.TH YANNY 8L "Oct 93" "Handmade"
+.TH YANNY 8L "Apr 95" "Handmade"
.SH NAME
yanny \- checks if a list of processes is still running
.SH SYNOPSIS
.B yanny
[
+-y
+.I filename
+]
+
+.B yanny
+[
-y
.I filename
]
[
-.B "<command to be started>"
+-p
+.I pidfilename
]
+.B "<command to be started>"

.B yanny
[
@@ -39,14 +47,25 @@
.I filename
instead of /etc/yanny.conf.
.TP
+.BI "-p " pidfilename
+Use
+.I pidfilename
+to find out the process ID of the daemon (this file must contain the
+process ID as the first line).
+.TP
.BI "-k " regex
Search for command matching
.I regex
and kill them. A TERM signal will be send to every matching process
and it will be removed from the configuration file.
+.SH LIMITATIONS
+Not all processes terminate when receiving a TERM signal.
.SH FILES
/etc/yanny.conf - yanny's database.
.SH SEE ALSO
scotty(1), exec(n), kill(2), crontab(1)
.SH AUTHORS
schoenw@ibr.cs.tu-bs.de (Kaept'n Koerg)
+.br
+patrick.weemeeuw@kulnet.kuleuven.ac.be (patched for process ID file
+support)
bash$