Update: Commenters have pointed out a few things:
- 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.
- There are other options, like
daemonize(1)
,setsid(1)
, and the bash builtindisown
(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.
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.
oh, look into upstart events, you no longer need to write daemons if you use them.
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.
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.
There’s also daemonize: http://www.clapper.org/software/daemonize/
As well as daemon(3) there’s daemonize:
[root@lenovo VTK]# urpmq -i daemonize
Name : daemonize
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.clapper.org/software/daemonize/
Summary : Run a command as a Unix daemon
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.
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.
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.
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.