免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 948 | 回复: 0
打印 上一主题 下一主题

How to Daemonize in Linux [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-18 15:06 |只看该作者 |倒序浏览

How to Daemonize in Linux
One of the things I keep running across is Linux daemons that don’t properly daemonize themselves. To properly daemonize, the following steps must be followed.

    The fork() call is used to create a separate process.
    The setsid() call is used to detach the process from the parent (normally a shell).
    The file mask should be reset.
    The current directory should be changed to something benign.
    The standard files (stdin,stdout and stderr) need to be reopened.

Failure to do any of these steps will lead to a daemon process that can misbehave. The typical symptoms are as follows.

    Starting the daemon and then logging out will cause the terminal to hang. This is particularly nasty with ssh.
    The directory from which the daemon was launched remains locked.
    Spurious output appears in the shell from which the daemon was started.

Simple Example
The following example program performs the bare minimum steps required to launch a daemon process.
#include
#include
#include
#include
#include
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
static void daemonize(void)
{
    pid_t pid, sid;
    /* already a daemon */
    if ( getppid() == 1 ) return;
    /* Fork off the parent process */
    pid = fork();
    if (pid  0) {
        exit(EXIT_SUCCESS);
    }
    /* At this point we are executing as the child process */
    /* Change the file mode mask */
    umask(0);
    /* Create a new SID for the child process */
    sid = setsid();
    if (sid daemonize();
    /* Now we are a daemon -- do the work for which we were paid */
    return 0;
}
It has been brought to my attention that a second call to fork() may be required to fully detach the process from the controller terminal (in other words: fork, setsid, fork). This does not seem to be required in Linux. A second fork would not cause any problems, although it would complicate the child/parent signalling below.
A More Useful Example
The following program extends the basic daemon by adding the following features.

    Logs messages to the system log (via syslog).
    Creates a lock file to prevent the daemon from being run twice.
    Changes the effective user (drops privileges).
    Startup errors are reported to the main process.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* Change this to whatever your daemon is called */
#define DAEMON_NAME "mydaemon"
/* Change this to the user under which to run */
#define RUN_AS_USER "daemon"
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
static void child_handler(int signum)
{
    switch(signum) {
    case SIGALRM: exit(EXIT_FAILURE); break;
    case SIGUSR1: exit(EXIT_SUCCESS); break;
    case SIGCHLD: exit(EXIT_FAILURE); break;
    }
}
static void daemonize( const char *lockfile )
{
    pid_t pid, sid, parent;
    int lfp = -1;
    /* already a daemon */
    if ( getppid() == 1 ) return;
    /* Create the lock file as the current user */
    if ( lockfile && lockfile[0] ) {
        lfp = open(lockfile,O_RDWR|O_CREAT,0640);
        if ( lfp pw_uid );
        }
    }
    /* Trap signals that we expect to recieve */
    signal(SIGCHLD,child_handler);
    signal(SIGUSR1,child_handler);
    signal(SIGALRM,child_handler);
    /* Fork off the parent process */
    pid = fork();
    if (pid  0) {
        /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
           for two seconds to elapse (SIGALRM).  pause() should not return. */
        alarm(2);
        pause();
        exit(EXIT_FAILURE);
    }
    /* At this point we are executing as the child process */
    parent = getppid();
    /* Cancel certain signals */
    signal(SIGCHLD,SIG_DFL); /* A child process dies */
    signal(SIGTSTP,SIG_IGN); /* Various TTY signals */
    signal(SIGTTOU,SIG_IGN);
    signal(SIGTTIN,SIG_IGN);
    signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
    signal(SIGTERM,SIG_DFL); /* Die on SIGTERM */
    /* Change the file mode mask */
    umask(0);
    /* Create a new SID for the child process */
    sid = setsid();
    if (sid Daemonize */
    daemonize( "/var/lock/subsys/" DAEMON_NAME );
    /* Now we are a daemon -- do the work for which we were paid */
    /* Finish up */
    syslog( LOG_NOTICE, "terminated" );
    closelog();
    return 0;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/93615/showart_1932182.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP