Daemonizing Processes

Update: Commenters have pointed out a few things:

  1. This post is incomplete/incorrect. What I’m doing now is having the daemon function call a script that looks like this:
    #!/bin/bash
    exec 1>&-
    exec 2>&-
    exec 3>&-
    nohup myPropApp & 2>&1 > thelog.txt

    That code was from another website who’s URL I lost, and I posted the solution below based on another, alternate method that I hadn’t tried but sounded simpler.

  2. There are other options, like daemonize(1), setsid(1), and the bash builtin disown (which I had prematurely rejected as ksh-only).

Back when I was using Debian, one of the nicer things about it was their helper tool for startup scripts: start-stop-daemon. Particularly, it’s ability to daemonize any process with the -b flag. You notice how handy things like that end up being when you’ve got an in-house or otherwise proprietary app that can’t daemonize itself properly (e.g. Java-based services).

Somehow I’ve managed to get away with not having to write a script that daemonizes a normally-foreground process on an RH-based distribution yet, mainly because I’ve been using Debian almost exclusively for servers, and have only worked for tiny startups, where luxuries like init scripts are the last thing on anyones’ minds.

Everyone is familiar with the nohup & trick, but that still leaves it associated to a terminal, so after you log out, your terminal/ssh session will just hang because stdin is still open. As it turns out, you can close your standard in from bash first by redirecting your standard input from nil (e.g. someapp <&-), and that will let it just work.

Very sweet for writing initscripts.

10 thoughts on “Daemonizing Processes

  1. Closing stdin is not enough. There is the chdir / and the double fork t
    plus setsid to set the daemonized process as session leader, otherwise some signals sent to the parent process reach the “daemon”. I dunno if start stop daemon implements all of this correctly, but your sh trick is doing it wrong.

  2. Damn, Rudd-O beat me to it. Take a look at daemon(3). setsid it the easiest way to do what you want. It does everything you want.

  3. Don’t forget about the ‘disown’ bash builtin:

    disown [-ar] [-h] [jobspec …]
    Without options, each jobspec is removed from the table of
    active jobs. If the -h option is given, each jobspec is not
    removed from the table, but is marked so that SIGHUP is not sent
    to the job if the shell receives a SIGHUP. If no jobspec is
    present, and neither the -a nor the -r option is supplied, the
    current job is used. If no jobspec is supplied, the -a option
    means to remove or mark all jobs; the -r option without a job-
    spec argument restricts operation to running jobs. The return
    value is 0 unless a jobspec does not specify a valid job.

    In other words, after invoking disown, if you close the associated terminal it doesn’t kill the job.

  4. Rudd-O/Jeff Schroeder:

    Unfortunately, my platform is RHEL5, so there’s no upstart, and the app I’m trying to deal with is Java, so I can’t call daemon(3).

    Luke:

    That’s actually a better solution, I had heard that was only in ksh, but apparently that’s not the case. Thanks for that.

  5. James,

    I wasn’t referring to upstart at all, I was referring to setsid. setsid is part of util-linux and installed by default on EVERY RHEL box.

    Here is one of our internal dns servers in asia:
    root@ns1.tyo01.mtt:~ # cat /etc/redhat-release
    Red Hat Enterprise Linux Server release 5 (Tikanga)
    root@ns1.tyo01.mtt:~ # rpm -qf `which setsid`
    util-linux-2.13-0.44.el5
    root@ns1.tyo01.mtt:~ # setsid
    usage: setsid program [arg …]

    Also, disown requires you to background the process. Something like:
    ./somecommand & disown -h

    Note the -h to disown, that keeps it from dying in the event of a sighup.

  6. Red Hat have long used a function in the /etc/init.d/functions script called daemon to daemonise processes. It allows passing optional nice level, a pidfile to track the resulting pid and a user to run as.

  7. Jeff:

    Sorry, I see daemon(3) and go into “library call, can’t use” mode. Rudd-O was referring to upstart.

    Alastair:

    Yeah, it doesn’t actually daemonize the process for you, though:

    $nice /bin/bash -c "$corelimit >/dev/null 2>&1 ; $*"

    It just launches it after setting a bunch of things, then checks the return value and prints the [OK]/[FAILED] messages.

Comments are closed.