c - 如何确保只有一个守护程序副本在运行?

标签 c linux daemon

我守护进程的代码是:

static int daemonize( const char *lockfile )
{
    pid_t pid, sid, parent;
    int lfp = -1;
    char buf[16];

    /* already a daemon */
    if ( getppid() == 1 ) return 1;

    /* Each copy of the daemon will try to 
     * create a file and write its process ID 
     * in it. This will allow administrators 
     * to identify the process easily
     */ 
    /* Create the lock file as the current user */
    if ( lockfile && lockfile[0] ) {
        lfp = open(lockfile,O_RDWR|O_CREAT,LOCKMODE); 
        if ( lfp < 0 ) {
            syslog( LOG_ERR, "unable to create lock file %s, code=%d (%s)",
                    lockfile, errno, strerror(errno) );
            exit(EXIT_FAILURE);
        }
    }

    /* If the file is already locked, then to ensure that 
     * only one copy of record is running. The filelock function will fail 
     * with errno set to EACCESS or EAGAIN.
     */
    if (filelock(lfp) < 0) {
        if (errno == EACCES || errno == EAGAIN) {
            close(lfp);
            //return(1);
            exit(EXIT_FAILURE);
        }
        syslog(LOG_ERR, "can't lock %s: %s", lockfile, strerror(errno));
        exit(EXIT_FAILURE);
    }
    ftruncate(lfp, 0);
    sprintf(buf, "%ld", (long)getpid());
    write(lfp, buf, strlen(buf)+1); 

    /* Drop user if there is one, and we were run as RUN_AS_USER */
    if ( getuid() == 0 || geteuid() == 0 ) {
        struct passwd *pw = getpwnam(RUN_AS_USER);
        if ( pw ) {
            syslog( LOG_NOTICE, "setting user to " RUN_AS_USER );
            setuid( pw->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) {
        syslog( LOG_ERR, "unable to fork daemon, code=%d (%s)",
                errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }
    /* If we got a good PID, then we can exit the parent process. */
    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 < 0) {
        syslog( LOG_ERR, "unable to create a new session, code %d (%s)",
                errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }

    /* Change the current working directory.  This prevents the current
       directory from being locked; hence not being able to remove it. */
    if ((chdir("/")) < 0) {
        syslog( LOG_ERR, "unable to change directory to %s, code %d (%s)",
                "/", errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }

    /* Redirect standard files to /dev/null */
    freopen( "/dev/null", "r", stdin);
    freopen( "/dev/null", "w", stdout);
    freopen( "/dev/null", "w", stderr);

    /* Tell the parent process that we are A-okay */
    kill( parent, SIGUSR1 );
    return 0;
}

我想在启动程序时一次只运行一个实例:

service [script] start

但是每当这个命令执行两次或更多次时,它会在运行状态下创建相同数量的守护进程。我想摆脱这种行为。任何建议将不胜感激。

最佳答案

不要使用文件锁;相反,使用 O_EXCL 标志到 open(),如果文件已经存在,它将失败并返回 EEXIST。这通常通过 pid 文件完成,因为无论如何它都需要是独占的。

关于c - 如何确保只有一个守护程序副本在运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5917018/

相关文章:

执行完成后关闭终端

linux - 查找固定长度的文件

linux - 守护进程和应用程序控制

c - mpfr_set_str 没有给出很好的值(value)

c - 这里有什么逻辑错误吗?

Linux 1604 : kestrel service can't find dotnet installation

linux - 使用哪个库在 Linux 中开发 Windows 管理器?

java - 退出无限循环

java - 如何处理从xml到Activity的点击

c - DNA split 算法