daemon

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.

Reference

daemon - Writing and packaging system daemons , systemd documentation
Describes both SysV daemons and New-Style daemons.

EMJ (2015-05-02) Note that systemd is somewhat controversial, and anything in its documentation about other ways of dealing with programs which are or claim to be "daemons" is almost certainly biased. In particular, "New-Style daemons" in the sentence above has to mean "systemd-style daemons". And those are conceptually no different from those managed by daemontools (see further down this page), i.e. they are not daemons at all - call them services if you like.

See Also

tcllauncher
includes ::tcllauncher::daemonize

Description

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 I submitted a setsid() patch for TclX a long while ago via email, must have fallen through the cracks. I'll see if I can find the patch and re-submit it.

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...


dzach: I'm trying to write a simple daemon for SuSE Linux 9.3 based on the above.

  • So far I managed to get the daemon started. But when trying to stop the daemon, nothing happens, but the panel shows daemon has stopped.
  • How can I set the runlevels for the daemon? There is nothing showing on the Yast panel.
  • How can I write a description for the daemon so that it shows up in the Yast2 panel?

Any ideas please?


AMG: I recommend against having a process daemonize itself. It's simpler overall if it instead relies on the shell to fork it into the background. This allows the shell to redirect its output to a log file or logger process, among other things. It centralizes the "daemonization" code in the parent shell, which is a better design than having every potential daemon process contain a (possibly buggy) copy.

Here's a bash example:

$ server.tcl &

The ampersand makes bash (or whatever shell) fork a child process to run server.tcl.

If you simply must have the process appear to daemonize itself, perhaps because your Linux distribution demands this, wrap it with a one-line shell script similar to the above example. This shell script can also set resource limits, redirect stdin/stdout/stderr, record PIDs, change UIDs, and contain configuration in the form of command-line arguments passed to the child.

See daemontools [L3 ] for a very robust implementation of this concept.

TP: Backgrounding a process with & can certainly make a long running process, and often survives after the current shell has ended, but this doesn't make a daemon in the Unix sense. The daemon entry in Wikipedia has the steps a process must perform in order to become a daemon [L4 ]. The major steps are disassociating with the controlling terminal and parent process group in order to avoid inheriting signals.

The two-step fork in the example above is designed to disassociate from the control terminal and the parent's process group and not to acquire a new controlling terminal. Other steps are changing to the root filesystem (so that the process doesn't have its current directory on a mounted filesystem, in case that filesystem needs to be unmounted) and setting a umask, usually 0 (022 was correct in the example for the server I was writing.)

Closing stdin/stdout/stderr file descriptors and re-opening them to /dev/null prevent a child process from blindly writing to stdout/stderr, and possibly writing over some other file that the parent daemon may have opened. I recall reading a long time back that some major database vendor closed stdio but failed to re-open file descriptors 0, 1, and 2 to /dev/null. The database I/O opened files to the database and Unix gave them the lowest file descriptors it had, namely 0, 1, 2, etc. At some time, the database forked off some minor administrative process which wrote a status message on stdout. Oops! the file descriptor number 1 that the child inherited from the parent was pointing to the database!

Note also that bash does some things that other shells don't, such as ignoring SIGQUIT and SIGHUP signals (by default). If you are running on a system that doesn't have bash, your backgrounded process may just terminate when you quit your interactive shell. nohup is commonly used to ignore SIGHUP and route stdout to a file (but such processes are still not daemons).

For Tcl, the daemon code above is probably a lot safer than relying on a specific shell's behavior. That is of course, if you truly want a daemon. AFAIK, the code above still works on Unixes from 15-20 years ago to modern-day versions.

AMG: Again, all these other steps toward daemonization can be done in the run script, as daemontools calls it. I recommend writing the run script in execline; its behavior is well defined and extremely simple.

MAKR 2007-02-08: AMG, you seem to fail to understand the daemon concept on Unix Systems. I recommend to get yourself a copy of W. Richard Stevens' book UNIX Network Programming and read chapter 13. The above mentioned daemontools do also ignore basic facts about daemons. And btw the author of the tools seems to have a strange understanding of Unix Systems and Software Engineering in general...

A good short introduction to daemons can also be found here [L5 ]. Provides example code in C.

AMG: What steps listed by TP can't be accomplished by a run script? The run script calls commands to redirect I/O, chroot, set a umask, set the user, fiddle with the process group, etc., anything necessary for the particular case. What's the difference between a single process image doing all these things for itself (thereby duplicating code) and chaining a series of daemonization tools with exec then exec'ing into the final process? Daemontools (or its parent, init) can get the ball rolling by setting a few things. I don't have source code in front of me to verify exactly what's being done and being left undone, but I do know that I have a happily working system using daemontools.

As for a strange understanding of software engineering, I find nothing strange about being simple. The only strange part is the nagging feeling that surely something must be missing, but the same has been said of Tcl. I can't find the quote right now, but it's somewhere on this wiki. I'll paraphrase: Whenever I show someone (who is accustomed to C socket programming) how to write a Tcl network program, he or she is always sure something is being left out. I suppose we've been conditioned to believe that software engineering is necessarily complex and that anything simple is liable to be inadequate. What a shame.

The strange understanding of Unix is, to my way of thinking, more a recognition that Unix systems have been made much more complicated than necessary by people insisting on constantly reinventing wheels rather than embracing the simple approach of chaining and reusing small components wherever possible. I think that said approach is the true heart and soul of Unix. A return to this may be breaking with current practice, but it is not necessarily the wrong thing to do.


EMJ: Much of the above discussion seems to depend on what is meant by a daemon. Perhaps we can agree on a functional definition to start with:

A daemon is a program which runs continuously until it is explicitly terminated (or the system shuts down), and which provides a specific service to other programs via a defined interface. For example, a web server listens on port 80 for HTTP requests to which it responds.

The traditional Unix daemon sets out to run forever by making itself totally independent of any other process (mainly, but not only, independent of signals sent to any other process). This is the purpose of the steps in TP's example at the top of the page - in fact they are the standard and widely published recipe for a daemon.

Another point of view is that daemons should be supervised, presumably in case they disappear for some reason. Of course you could say that a daemon which disappears must have a bug to be fixed, but there may still be a valid reason for supervising daemons.

In that case the supervising program should almost certainly be a traditional daemon itself, so that no other process can affect the supervised daemons. But then there is at least one problem: if the supervisor disappears, what should the "daemons" do?

An old hacker folktale [L6 ] provides one solution: make sure there are two supervisors (who of course should supervise each other).

The key thing that allows a daemon to keep providing its service is its independence, which, l think, is what AMG has missed.


I would have to support AMG's position here and anyone claiming that the daemontools are not managing "traditional" UNIX daemons hasn't understood what they do. AMG is glossing over the fact that when he says "shell script" he really means a shell script which calls "supervise". This program from daemontools sets up the environment and calls your program, including the io, controlling terminal and process group. The idea in daemontools that AMG is trying to express is that you put the code explained in Stevens in one program, then it sets up the daemon's environment and execs the service. You don't need to proliferate the Stevens code into every daemon and rewrite it in every language. You really have to read the docs. D.J. is a UNIX wizard- JBR


EMJ: "hasn't understood" - meaning me I suppose, but the point you are missing is that a process managed by supervise is not totally independent of any other process, and hence is not what I referred to as a traditional daemon. Using supervise or anything else to manage a run-forever program just encourages not caring about occasional but fatal bugs. Having something to watch and restart daemons should be no more than a temporary expedient till a bug is fixed, and even then the daemons should still be totally independent of the watcher once they are started.

DJB's FAQ for daemontools doesn't even mention independence, as if it was not even possible for independence to be important. And just what is it that determines his wizard status?


JBR: What is the purpose of init? It is just a super-supervise. You could view the process pair (or group) as independent cooperating process to accomplish a service.

DJB is a wizard because he has designed some truly nice software that fits hand and glove with the UNIX way. It is my HO only I suppose.


DRF: Apple's Mac OS X has a new way of launching programs like this. [L7 ] This launchd daemon handles all the things that init, cron, etc. handle. OS X still has those daemons if you want to use them, but launchd is the new hotness.