一尘不染

在Linux中创建守护程序

linux

在Linux中,我想添加一个无法停止且监视文件系统更改的守护程序。如果检测到任何更改,则应在启动控制台的路径上加上换行符。

我已经准备好更改代码的文件系统了,但是我不知道如何创建守护程序。

我的代码来自这里:http :
//www.yolinux.com/TUTORIALS/ForkExecProcesses.html

叉后该怎么办?

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;
}

阅读 248

收藏
2020-06-02

共1个答案

一尘不染

在Linux中,我想添加一个无法停止且监视文件系统更改的守护程序。如果将检测到任何更改,则应将路径写入启动它的控制台+换行符。

守护程序在后台工作,并且(通常…)不属于TTY,这就是为什么您无法以可能想要的方式使用stdout /
stderr的原因。通常,使用syslog守护程序( syslogd )将消息记录到文件中(调试,错误等)。

除此之外,还有一些 必需的步骤 来守护进程。


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

  • 分叉 父进程,如果分叉成功,则终止它。->由于父进程已终止,因此子进程现在在后台运行。
  • setsid- 创建一个新会话。调用过程将成为新会话的负责人和新过程组的过程组负责人。现在,该过程已从其控制终端(CTTY)分离。
  • 捕获信号 -忽略和/或处理信号。
  • 再次分叉并 让父进程终止,以确保您摆脱了会话引导进程。(只有会议负责人才能再次获得TTY。)
  • chdir- 更改守护程序的工作目录。
  • umask- 根据守护程序的需要更改文件模式掩码。
  • close- 关闭所有可能从父进程继承的打开文件描述符。

为您提供一个起点:查看显示基本步骤的此框架代码。现在,也可以在GitHub上分叉此代码:linux守护程序的基本框架

/*
 * 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;
}
  • 编译代码: 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 (初始化进程)
  • PID!= SID ,这意味着我们的进程不是会话组长
    (因为第二叉())

  • 由于PID!= SID,我们的过程 无法再次控制TTY

读取系统日志:

  • 找到您的系统日志文件。我的在这里:/var/log/syslog
  • 做一个: grep firstdaemon /var/log/syslog

  • 输出应与此类似:

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

注意: 实际上,您还需要实现信号处理程序并正确设置日志记录(文件,日志级别…)。

进一步阅读:

2020-06-02