Version 7 of daemon

Updated 2003-01-07 20:24:17

Unix people generally understand "daemon" to be a long-running process, disconnected from any TTY, perhaps with signal management configured in a particular way. This corresponds closely to services under Microsoft Windows NT.

[... start ...]

Tom Poindexter posted [L1 ] this example implementation:

 package require Tclx
 proc shutdown {} {
   # whatever cleanup you need to do
   exit
 }

 proc dispatcher {} {
   # do your work here!  this sample just opens a log file and writes to it.
   while 1 {
     set fd [open /tmp/daemon2.log w]
     puts $fd "daemon2.tcl last ran at [clock format [clock seconds]]" 
     close $fd
     sleep 5
   }
 }
 proc daemonize {} {
   close stdin
   close stdout
   close stderr
   if {[fork]} {exit 0}
   id process group set
   if {[fork]} {exit 0}
   set fd [open /dev/null r]
   set fd [open /dev/null w]
   set fd [open /dev/null w]
   cd /
   umask 022
   return [id process]
 }
 daemonize
 signal ignore  SIGHUP
 signal unblock {QUIT TERM}
 signal trap    {QUIT TERM} shutdown
 dispatcher

Tom wrote this as a Tcl (or, more properly, TclX) translation of a C-coded example which appeared in W. Richard Stevens' Unix Network Programming. Tom notes that Expect also has enough of the POSIX API "to dissociated from the tty, set umask, become a new process group leader, etc." In fact, BOOK Exploring Expect devotes an entire chapter to "Background Processing".

[Tom might work on setsid() access (by way of a patch) at some point.]

TP - changed the 'after 5000' to 'sleep 5', which should work better. I noticed some problems with signals and after. TclX's 'sleep' sets a traditional Unix alarm(2) system call. [Tom, are the problems something the after maintainer should fix?]


[Explanation of the open /dev/null ...s:]

In Unix, a successful open() call traditionally returns the smallest currently-unused file descriptor. So if you close file descriptors 0, 1, and 2 (standard input, standard output, resp. standard error), the next three files you open will be assigned FDs 0, 1, and 2. This is the traditional way to reassign standard input, etc. (The modern way is to use dup2(), BTW.)

Tcl's channel system contains some black magic that emulates this behaviour for the channels stdin, stdout, and stderr; see Tcl_StandardChannels(3) [L2 ] for details.

The daemonize proc closes stdin, stdout, and stderr in order to detach from the inherited standard file descriptors, then opens /dev/null three times so that it will get a new stdin, stdout, and stderr.


    nohup tclsh my_daemon .... &

Is generally useful for "putting a process in the background" while suppressing SIGHUPs to my_daemon.

And it's even more useful if you redirect stderr/stdout to a file that is named mnemonically...