一个进程在Linux下结束时如何得到通知?

我如何监视一些进程,如果一个进程结束,我想运行一些代码。

我发现了几个使用轮询来实现这个function的例子,但是我正在寻找一种方法,当某个进程死亡时,它可能被操作系统(可能是通过操作系统)执行。 这是可能的C或C + +? 它应该在任何现代Linux上运行。

如果有机会,我想这样做,而不需要root权限。

编辑:

整个程序的工作是监视这些进程,并将这些信息发送到另一台服务器,并将其整合到一个网站中。

我还没有开始这些stream程,但我可以确保它们是以相同的用户身份启动的。

我认为这应该是可能的,因为在Linux下的top / ps命令也给你关于你还没有启动的进程的信息。

通常在Linux上,不能通知(使用waitpid(2)或SIGCHLD – 请参阅signal(7) – …)关于非子进程或进程组或会话之外的进程。

而在某些Linux系统中,你的(非root)进程可能甚至不允许查询其他进程的存在。

当然, /proc/ (每个进程都有一个数字命名的目录,例如/proc/1234/用于进程pid 1234,请参阅proc(5) ),您可能会定期扫描(例如,使用readdir(3)) 。 ),但不能通知你(见inotify(7) ,这对伪文件系统(如/proc/ …) 不起作用 。 请注意, /proc/是一个伪文件系统,访问它不涉及任何磁盘IO,因此速度非常快。

所以你可以做的是使用opendir(3) , readdir , closedir(3) , sleep(3)循环扫描/proc/每隔几秒钟。 顺便说一句,从理论上来说,这并不是一个防错措施(原则上,实际上,内核可能会在几秒钟内重复使用同一个pid),并且可能不会捕获所有短命的进程(如ls shell命令)。

/proc这种定期扫描很可能是top(1)工具正在做的事情。 你可以通过跳入top的源代码或strace(1)来检查它。

如果你的C代码已经知道某个进程的pid,并且只想检查该进程的存在,那么可以使用kill(2)和一个0号信号。

另请参阅systemd和凭证(7) 。

如果你可以改变被监控程序的代码或者替换它们(例如,用你的小C程序包装它们),情况就大不一样了。 例如,你可以用/usr/local/bin/foo-wrapper来代替/usr/bin/foo ,并且编写一个foo-wrapper.c fork -s& exec -s原来的/usr/bin/foo然后waitpid(2)在它上面,最后在某个套接字(7)或fifo(7)或管道(7)上发送(2)或写入(2)一些消息,并在监视器中使用基于poll(2)的事件循环 。 如果你可以通过你的显示器获得所有的程序,那么事情也是不同的(使用waitpid …)。 看到我的execicar.c程序的灵感。

您可以配置auditd守护进程以在进程结束时创建审计记录(日志行)。 然后使用inotify监视auditd日志文件。

只要您有权访问auditd配置及其日志文件。

注意/ proc /目录为每个正在运行的进程保存一个目录,比如/ proc / 1是PID 1

在那个目录下有一个cmdline文件,可以用来确定PID的命令,例如:cat / proc / 1 / cmdline / usr / lib / systemd / systemd

你可以遍历/ proc / [09] *目录寻找符合你所寻找的cmdline,当你匹配的命令,你可以简单地检查cmdline是否仍然匹配原来的(相同的PID可以用于另一个过程是否已经终止

这里有一个简单的代码就可以完成这项工作:我没有写出大部分的错误更正(如果找不到应用程序,则会导致程序崩溃,还有一些导致段错误的错误)#include #include #include

 int main(int argc, char* argv[]) { if (argc != 2){ printf("usage:\nproc <processname>\n"); return 2; } char * processName = argv[1]; int pid = 0; FILE *processFile; char *monitoredProcess; DIR *root; struct dirent *dir; root = opendir("/proc/"); if (root) { int reading = 0; while((dir=readdir(root))!=NULL && reading==0) { // printf("dir name:%i\n",dir->d_ino); if (dir->d_name[0] > 47 && dir->d_name[0] < 58) { char directory[128]; strcpy(directory,"/proc/"); strcat(directory,dir->d_name); strcat(directory,"/cmdline"); processFile = fopen(directory,"r"); if (processFile == NULL) { printf("Error"); return 1; } char line[2048]; while (fgets(line, sizeof line, processFile) != NULL) { if(strstr(line,processName)) { printf("%s\n",directory); monitoredProcess = directory; reading = 1; } //the pid has been determined at this point, now to monitor } } } //monitoring printf("monitoring %s\n",monitoredProcess); while(processFile=fopen(monitoredProcess,"r")) { char line[2048]; while (fgets(line, sizeof line, processFile) != NULL) { if(strstr(line,processName) == NULL) printf("application terminated\n"); } sleep(3); fclose(processFile); } } else printf("unable to open folder\n"); }