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.

  • Add to favorites
  • del.icio.us
  • Digg
  • email
  • Fark
  • Google Bookmarks
  • Identi.ca
  • Ping.fm
  • Print
  • Reddit
  • Slashdot
  • StumbleUpon
  • Tumblr
  • Twitter

Links

  • If you link to this post from your blog, a link back to your post will go here.

Comments

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

  • Rudd-O says:

    oh, look into upstart events, you no longer need to write dae­mons if you use them.

  • Damn, Rudd-O beat me to it. Take a look at daemon(3). set­sid it the eas­i­est way to do what you want. It does every­thing you want.

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

  • As well as daemon(3) there’s daemonize:

    [root@lenovo VTK]# urpmq –i dae­mo­nize
    Name : dae­mo­nize
    Version : 1.5.2
    Release : 2mdv2009.0
    Group : System/Servers
    Size : 18177 Architecture: i586
    Source RPM : daemonize-1.5.2-2mdv2009.0.src.rpm
    URL : http://​www​.clap​per​.org/​s​o​f​t​w​a​r​e​/​daemonize/
    Summary : Run a com­mand as a Unix daemon

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

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

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

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

  • If you reply to this post, your reply will go here.

Reply