Daemonizing Processes

Update: Commenters have pointed out a few things:

  1. This post is incomplete/incorrect. What I’m doing now is hav­ing the daemon func­tion 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 web­site who’s URL I lost, and I posted the solu­tion below based on another, alter­nate 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 pre­ma­turely 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 abil­ity to dae­mo­nize any process with the -b flag. You notice how handy things like that end up being when you’ve got an in-house or oth­er­wise pro­pri­etary app that can’t dae­mo­nize itself prop­erly (e.g. Java-based services).

Somehow I’ve man­aged to get away with not hav­ing to write a script that dae­mo­nizes a normally-foreground process on an RH-based dis­tri­b­u­tion yet, mainly because I’ve been using Debian almost exclu­sively for servers, and have only worked for tiny star­tups, where lux­u­ries like init scripts are the last thing on any­ones’ minds.

Everyone is famil­iar with the nohup & trick, but that still leaves it asso­ci­ated to a ter­mi­nal, so after you log out, your terminal/ssh ses­sion will just hang because stdin is still open. As it turns out, you can close your stan­dard in from bash first by redi­rect­ing your stan­dard input from nil (e.g. someapp <&-), and that will let it just work.

Very sweet for writ­ing initscripts.

10 Responses

  1. Rudd-O says:

    Closing stdin is not enough. There is the chdir / and the dou­ble fork t
    plus set­sid to set the dae­mo­nized process as ses­sion leader, oth­er­wise some sig­nals sent to the par­ent process reach the “dae­mon”. I dunno if start stop dae­mon imple­ments all of this cor­rectly, but your sh trick is doing it wrong.

  2. Luke says:

    Don’t for­get about the ‘dis­own’ bash builtin:

    dis­own [-ar] [-h] [job­spec …]
    Without options, each job­spec is removed from the table of
    active jobs. If the –h option is given, each job­spec 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 job­spec is
    present, and nei­ther the –a nor the –r option is sup­plied, the
    cur­rent job is used. If no job­spec is sup­plied, the –a option
    means to remove or mark all jobs; the –r option with­out a job–
    spec argu­ment restricts oper­a­tion to run­ning jobs. The return
    value is 0 unless a job­spec does not spec­ify a valid job.

    In other words, after invok­ing dis­own, if you close the asso­ci­ated ter­mi­nal it doesn’t kill the job.

  3. James Cape says:

    Rudd-O/Jeff Schroeder:

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

    Luke:

    That’s actu­ally a bet­ter solu­tion, I had heard that was only in ksh, but appar­ently that’s not the case. Thanks for that.

  4. James,

    I wasn’t refer­ring to upstart at all, I was refer­ring to set­sid. set­sid is part of util-linux and installed by default on EVERY RHEL box.

    Here is one of our inter­nal 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 set­sid‘
    util-linux-2.13 – 0.44.el5
    root@ns1.tyo01.mtt:~ # set­sid
    usage: set­sid pro­gram [arg …]

    Also, dis­own requires you to back­ground the process. Something like:
    ./somecommand & dis­own –h

    Note the –h to dis­own, that keeps it from dying in the event of a sighup.

  5. Alastair says:

    Red Hat have long used a func­tion in the /etc/init.d/functions script called dae­mon to dae­monise processes. It allows pass­ing optional nice level, a pid­file to track the result­ing pid and a user to run as.

  6. James Cape says:

    Jeff:

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

    Alastair:

    Yeah, it doesn’t actu­ally dae­mo­nize the process for you, though:

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

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

Leave a Reply

*