在 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/