I just faced this problem at work and found a great little document that gave me the insight I needed. I'm posting it here for anyone else who is interested.
http://www.linuxprofilm.com/articles/linux-daemon-howto.html
Update
This page is currently the most popular on the site and it was well overdue for a refresh.
As stated in comments below the simplest way to do this in Linux is to use the daemon() system call. However, this function does not exist in System V based Unix distributions (ie, Solaris).
The basic concept that needs to happen is that your application forks itself and shuts down its standard input/output/error connections.
The C++ code I use for this is:
//! daemonize the currently running programming
//! Note: the calls to strerror are not thread safe, but that should not matter
//! as the application is only just starting up when this function is called
//! \param[in] dir which dir to ch to after becoming a daemon
//! \param[in] stdinfile file to redirect stdin to
//! \param[in] stdoutfile file to redirect stdout from
//! \param[in] stderrfile file to redirect stderr to
void System::daemonize(const string &dir = "/",
const std::string &stdinfile = "/dev/null",
const std::string &stdoutfile = "/dev/null",
const std::string &stderrfile = "/dev/null")
{
umask(0);
rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
{
//can't get file limit
throw std::runtime_error(strerror(errno));
}
pid_t pid;
if ((pid = fork()) < 0)
{
//Cannot fork!
throw std::runtime_error(strerror(errno));
} else if (pid != 0) { //parent
exit(0);
}
setsid();
if (!dir.empty() && chdir(dir.c_str()) < 0)
{
// Oops we couldn't chdir to the new directory
throw std::runtime_error(strerror(errno));
}
if (rl.rlim_max == RLIM_INFINITY)
{
rl.rlim_max = 1024;
}
// Close all open file descriptors
for (unsigned int i = 0; i < rl.rlim_max; i++)
{
close(i);
}
int fd0 = open(stdinfile.c_str(), O_RDONLY);
int fd1 = open(stdoutfile.c_str(),
O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
int fd2 = open(stderrfile.c_str(),
O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
{
//Unexpected file descriptors
throw runtime_error("new standard file descriptors were not opened as expected");
}
}By removing the references to std::string and throw this code is easily converted to C code.
The book "Advanced Programming in the UNIX Environment" covers in depth how to deamonize a process, why you would want to and what happens under the hood. I keep it as a desk reference and highly recommend it.
The hardback version:
And paperback is now available too:
Comments
A bit complex
Using the daemon() system call would eliminate 3/4 of the program.
If it exists...
The daemon() system call would have been a good choice at the time that I posted that comment, good point. However, it is a nonstandard call and may or may not exist on the platform you are writing for.
Linux Daemon how-to document gone!
Ah well.. looks like that how-to write a Daemon article is toast. Anybody have a copy of their own - there was a PDF originally as well. Looking to create some Daemons using C on embedded Linux.
Thanks muchly.
http://www.linuxprofilm.com/a
http://www.linuxprofilm.com/articles/linux-daemon-howto.html
http://web.archive.org/web/20
http://web.archive.org/web/20060603181849/http://www.linuxprofilm.com/ar...
Thank you
Linux Rules!
Thank you.
how to restart a daemon after it terminates in source code
I am trying to find a way to restart (respawn) the daemon after it dies, is there a way to do this in the daemon source code?
Thanks
Mike
Respawning a killed Daemon
Well. I am not aware of a way of doing this in the Daemon's source code itself. I don't think it is even possible because if you application is dead, there is nothing much it can do to revive itself. :-) What can be done instead is to have an entry for your Daemon in /etc/inittab specifying the "respawn" option. This way, init will take care of respawning your Daemon if it is killed.
Re: Respawning a killed Daemon
As a partial solution, you can install signal handlers in your daemon to respond to some signals. (SIGTERM maybe). But there is nothing much you can do about SIGKILL. So, /etc/inittab is a complete solution.