在 Linux 中创建守护进程

标签 c linux daemon

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

我几乎已经准备好文件系统更改代码,但我不知道如何创建守护进程。

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

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.

守护进程在后台工作并且(通常......)不属于 TTY,这就是为什么你不能以你可能想要的方式使用 stdout/stderr 的原因。 通常系统日志守护进程 (syslogd) 用于将消息记录到文件(调试、错误...)。

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


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

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

给您一个起点:查看显示基本步骤的框架代码。此代码现在也可以在 GitHub 上 fork :Basic skeleton of a linux daemon

/*
 * 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  | TIME | CMD |
+------+------+------+------+-----+-------+------+------+------+-----+
|    1 | 3387 | 3386 | 3386 | ?   |    -1 | S    | 1000 | 0:00 | ./  |
+------+------+------+------+-----+-------+------+------+------+-----+

你应该在这里看到的是:

  • 守护进程没有控制终端(TTY = ?)
  • 父进程ID(PPID)是1(init进程)
  • PID != SID 这意味着我们的进程不是 session 负责人
    (因为第二次fork())
  • 因为 PID != SID 我们的进程不能再次控制 TTY

读取系统日志:

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

  • 输出应该类似于这个:

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


备注: 实际上,您还希望实现信号处理程序并正确设置日志记录(文件、日志级别...)。

进一步阅读:

关于在 Linux 中创建守护进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35841546/

相关文章:

linux - 具有运行线程的相关进程的 POSIX 信号量

linux shell获取多文件交集

Java 作为 Unix 服务运行

c - 如何从字符串初始化字符数组,其间具有特殊的十六进制值

c++ - 如果异常被抛出 "through"c 代码会发生什么?

c - 使用无符号整数时循环条件停止在 0?

linux - 作为守护进程运行程序返回错误的 pid

python - 如何将 FANN 保存为字符串?

linux - 通过 SSH 访问远程 Git 存储库时使用 su/sudo

python - 使用 Python 列出 linux 中的所有守护进程/服务名称?