建立在Linux中守护进程 [英] Creating a daemon in Linux

查看:207
本文介绍了建立在Linux中守护进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Linux的我想补充一点,不能停止和监视文件系统变化的守护进程。
如果检测到任何变化,应该写的路径,它被启动控制台加一个换行符。

我已经有文件系统的变化code几乎准备好,但我无法弄清楚如何创建一个后台进程。

我的code是从这里开始:<一href=\"http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html\">http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

叉后做什么?

  INT主(INT ARGC,字符** argv的){  将为pid_t PID =叉();
  如果(PID == 0){//子
          // code只能由子进程执行
      sIdentifier =子进程;
    }
    否则如果(PID℃,){
        CERR&LT;&LT; 失败到餐桌&LT;&LT; ENDL;
        出口(1);
       //抛出异常
    }
    别的家长//
    {
      // code只能由父进程执行      sIdentifier =父进程;
    }    返回0;
}


解决方案

  

在Linux的我想补充一点,不能停止和监视文件系统变化的守护进程。如果有任何变化将被检测到,应该写的路径,它被启动+换行控制台。


守护在后台工作,并(通常...)不属于一个TTY这就是为什么你不能在你可能想要的方式使用标准输出/标准错误。
通常,syslog守护进程(的syslogd 的)用于记录消息的文件(调试,错误,...)。

除此之外,也有少数的必需步骤的以守护进程的过程。


如果我没有记错这些步骤是:


  • 关闭父进程和放大器;让它终止,如果分叉成功。 - >由于父进程已经终止,子进程,现在在后台运行

  • setsid - 创建一个新的会话。调用进程成为新的会话和新进程组的进程组组长的领导者。这个过程现在从它的控制终端(CTTY)。分离

  • 捕捉信号 - 忽略和/或处理信号

  • 叉再次&安培;让父进程终止,以确保您摆脱会话领先工艺。 (仅限会议的领导人可能会再次获得一个TTY)。

  • CHDIR - 更改守护进程的工作目录

  • 的umask - 根据守护进程的需要更改文件模式掩码

  • 关闭 - 可以从父进程继承关闭所有打开的文件描述符


要给你一个起点:看看这个骨架code,显示的基本步骤:

/ *
 * daemonize.c
 *这个例子daemonizes的过程,写了几日志消息,
 *睡20秒,终止之后。
 * /#包括LT&;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&signal.h中GT;
#包括LT&; SYS / types.h中&GT;
#包括LT&; SYS / stat.h&GT;
#包括LT&;&syslog.h GT;静态无效skeleton_daemon()
{
    将为pid_t PID;    / *叉掉父进程* /
    PID =叉();    / *出错* /
    如果(PID℃,)
        出口(EXIT_FAILURE);    / *成功:让家长终止* /
    如果(PID大于0)
        出口(EXIT_SUCCESS);    / *成功时:孩子过程变得会议的领导者* /
    如果(setsid()℃,)
        出口(EXIT_FAILURE);    / *捕捉,忽略和处理信号* /
    // TODO:实现工作信号处理* /
    信号(SIGCHLD,SIG_IGN);
    信号(SIGHUP,SIG_IGN);    / *叉关闭所述第二时间* /
    PID =叉();    / *出错* /
    如果(PID℃,)
        出口(EXIT_FAILURE);    / *成功:让家长终止* /
    如果(PID大于0)
        出口(EXIT_SUCCESS);    / *设置新的文件权限* /
    的umask(0);    / *更改工作目录的根目录* /
    / *或其他拨付目录* /
    CHDIR(/);    / *关闭所有打开的文件描述符* /
    INT X;
    为(X =的sysconf(_SC_OPEN_MAX); X大于0; x--)
    {
        关闭(X);
    }    / *打开日志文件* /
    openlog(firstdaemon,LOG_PID,LOG_DAEMON);
}

 

INT的main()
{
    skeleton_daemon();    而(1)
    {
        // TODO:插入守护code在这里。
        系统日志(LOG_NOTICE,第一守护进程启动。);
        睡眠(20);
        打破;
    }    系统日志(LOG_NOTICE,第一守护进程终止。);
    closelog();    返回EXIT_SUCCESS;
}

结果


  • 编译code:的gcc -o firstdaemon daemonize.c

  • 启动守护程序: ./ firstdaemon

  • 检查是否一切正常: PS -Xj | grep的firstdaemon


  • 输出应与此类似:



+ ------ + ------ + ------ + ------ + ----- + ------- ------ + + ------ + ------ + ----- +
| PPID | PID | PGID | SID | TTY | TPGID | STAT | UID |时间| CMD |
+ ------ + ------ + ------ + ------ + ----- + ------- ------ + + ------ + ------ + ----- +
| 1 | 3387 | 3386 | 3386 | ? | -1 | S | 1000 | 0:00 | ./ |
+ ------ + ------ + ------ + ------ + ----- + ------- ------ + + ------ + ------ + ----- +

你应该在这里看到的是:


  • 该守护进程没有控制终端( TTY =?

  • 父进程ID( PPID )为 1 (init进程)

  • PID!= SID 这意味着我们的过程是不是会话组长结果
    (因为第二叉的())

  • 由于PID!= SID我们的流程不能再采取TTY的控制权

阅读系统日志:


  • 找到您的syslog文件。我的是在这里:的/ var / log / syslog的

  • 做一个:的grep firstdaemon的/ var / log / syslog的


  • 输出应与此类似:



  firstdaemon [3387]:第一个守护进程启动。
  firstdaemon [3387]:第一个守护进程终止。

结果
的说明:
在现实中,你也想实现一个信号处理程序,并设置适当的日志记录(文件,日志级别...)。

延伸阅读:

In Linux I want to add a daemon that cannot be stopped and which monitors filesystem changes. If any changes are detected, it should write the path to the console where it was started plus a newline.

I already have the filesystem changing code almost ready but I cannot figure out how to create a daemon.

My code is from here: http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

What to do after the fork?

int main (int argc, char **argv) {

  pid_t pID = fork();
  if (pID == 0)  {              // child
          // Code only executed by child process    
      sIdentifier = "Child Process: ";
    }
    else if (pID < 0) {
        cerr << "Failed to fork" << endl;
        exit(1);
       // Throw exception
    }
    else                                   // parent
    {
      // Code only executed by parent process

      sIdentifier = "Parent Process:";
    }       

    return 0;
}

解决方案

In Linux i want to add a daemon that cannot be stopped and which monitors filesystem changes. If any changes would be detected it should write the path to the console where it was started + a newline.

Daemons work in the background and (usually...) don't belong to a TTY that's why you can't use stdout/stderr in the way you probably want. Usually a syslog daemon (syslogd) is used for logging messages to files (debug, error,...).

Besides that, there are a few required steps to daemonize a process.


If I remember correctly these steps are:

  • fork off the parent process & let it terminate if forking was successful. -> Because the parent process has terminated, the child process now runs in the background.
  • setsid - Create a new session. The calling process becomes the leader of the new session and the process group leader of the new process group. The process is now detached from its controlling terminal (CTTY).
  • Catch signals - Ignore and/or handle signals.
  • fork again & let the parent process terminate to ensure that you get rid of the session leading process. (Only session leaders may get a TTY again.)
  • chdir - Change the working directory of the daemon.
  • umask - Change the file mode mask according to the needs of the daemon.
  • close - Close all open file descriptors that may be inherited from the parent process.

To give you a starting point: Look at this skeleton code that shows the basic steps:

/*
 * daemonize.c
 * This example daemonizes a process, writes a few log messages,
 * sleeps 20 seconds and terminates afterwards.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>

static void skeleton_daemon()
{
    pid_t pid;

    /* Fork off the parent process */
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* On success: The child process becomes session leader */
    if (setsid() < 0)
        exit(EXIT_FAILURE);

    /* Catch, ignore and handle signals */
    //TODO: Implement a working signal handler */
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    /* Fork off for the second time*/
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* Set new file permissions */
    umask(0);

    /* Change the working directory to the root directory */
    /* or another appropriated directory */
    chdir("/");

    /* Close all open file descriptors */
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>0; x--)
    {
        close (x);
    }

    /* Open the log file */
    openlog ("firstdaemon", LOG_PID, LOG_DAEMON);
}

int main()
{
    skeleton_daemon();

    while (1)
    {
        //TODO: Insert daemon code here.
        syslog (LOG_NOTICE, "First daemon started.");
        sleep (20);
        break;
    }

    syslog (LOG_NOTICE, "First daemon terminated.");
    closelog();

    return EXIT_SUCCESS;
}


  • Compile the code: gcc -o firstdaemon daemonize.c
  • Start the daemon: ./firstdaemon
  • Check if everything is working properly: ps -xj | grep firstdaemon

  • The output should be similar to this one:

+------+------+------+------+-----+-------+------+------+------+-----+
| PPID | PID  | PGID | SID  | TTY | TPGID | STAT | UID  | TIME | CMD |
+------+------+------+------+-----+-------+------+------+------+-----+
|    1 | 3387 | 3386 | 3386 | ?   |    -1 | S    | 1000 | 0:00 | ./  |
+------+------+------+------+-----+-------+------+------+------+-----+

What you should see here is:

  • The daemon has no controlling terminal (TTY = ?)
  • The parent process ID (PPID) is 1 (The init process)
  • The PID != SID which means that our process is NOT the session leader
    (because of the second fork())
  • Because PID != SID our process can't take control of a TTY again

Reading the syslog:

  • Locate your syslog file. Mine is here: /var/log/syslog
  • Do a: grep firstdaemon /var/log/syslog

  • The output should be similar to this one:

  firstdaemon[3387]: First daemon started.
  firstdaemon[3387]: First daemon terminated.


A note: In reality you would also want to implement a signal handler and set up the logging properly (Files, log levels...).

Further reading:

这篇关于建立在Linux中守护进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆