在 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。 通常使用 syslog 守护进程 (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(初始化进程)
- 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/17954432/