linux下进程结束时如何得到通知?

Posted

技术标签:

【中文标题】linux下进程结束时如何得到通知?【英文标题】:How to get notified when a process ends under linux? 【发布时间】:2016-04-20 10:15:05 【问题描述】:

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

我找到了几个使用轮询来实现此目的的示例,但我正在寻找一种在进程终止时被推送(可能由操作系统)的方法。这可以用 C 或 C++ 实现吗?它应该可以在任何现代 Linux 上运行。

如果有任何机会,我想在不需要 root 权限的情况下这样做。

编辑:

整个程序的工作是监控这些过程并将这些信息发送到另一个服务器,然后将其集成到网站中。

我还没有启动这些进程,但我可以确保它们是作为同一用户启动的。

我认为这应该是可能的,因为 Linux 下的 top / ps 命令还可以为您提供有关您尚未启动的进程的信息。

【问题讨论】:

问题应该是“这在 Linux 上是否可行”。那么C部分就没有问题了。 关于 root:您是否可以只收到有关您的用户进程的通知? (我什至根本不知道这样的通知是否可能,但如果是,我确信只有 root 才能为 all 进程执行此操作) 我怀疑是否有人使用轮询来查找进程是否已终止。 wait()sigaction() /w SIGCHLD. 看***.com/a/28602298/3134621 @EOF 这个只能对子进程执行,一般不行 【参考方案1】:

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

在该目录下有 cmdline 文件,可用于确定 PID 的命令,即: 猫 /proc/1/cmdline /usr/lib/systemd/systemd

您可以遍历 /proc/[09]* 目录来查找与您要查找的内容匹配的 cmdline,当您匹配该命令时,您可以简单地检查 cmdline 是否仍然与原始命令匹配(可以是相同的 PID如果它已终止,则用于另一个进程

这里有一段简单的代码可以完成这项工作: 我还没有写大部分的纠错(如果找不到应用程序,程序会崩溃,其他一些导致段错误的错误) #包括 #包括 #包括

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");

【讨论】:

这是轮询,OP 已经声明有代码。问题是 notification 是否可行。【参考方案2】:

一般而言,在 Linux 上,您无法收到有关非子进程或进程组或会话之外的进程的通知(使用 waitpid(2) 或 SIGCHLD -see 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),并且可能不会捕获所有 short-living 进程(如ls shell 命令)。

/proc 的这种定期扫描很可能是 top(1) 实用程序正在执行的操作。您可以通过深入了解top 的源代码或strace(1)-ing 来检查它。

如果您的 C 代码已经知道某个进程的 pid 并且只是想检查该进程是否存在,它可以使用带有信号编号 0 的kill(2)。

另见systemd & credentials(7)。

如果您可以更改被监控程序的代码或替换它们(例如,通过您的小型 C 程序包装它们),情况就会大不相同;例如您可以用/usr/local/bin/foo-wrapper 替换/usr/bin/foo 并编码foo-wrapper.c 其中fork-s & exec-s 原始/usr/bin/foo 然后waitpid(2) 就可以了,最后send(2) 或write(2) 一些消息在某些socket(7) 或fifo(7) 或pipe(7) 上,并在您的监视器中使用基于poll(2) 的event loop。如果您可以通过监视器获取所有程序fork-ed,那么情况也会有所不同(使用waitpid...)。请参阅我的 execicar.c 程序以获取灵感。

【讨论】:

【参考方案3】:

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

前提是您有权访问auditd 配置及其日志文件。

【讨论】:

以上是关于linux下进程结束时如何得到通知?的主要内容,如果未能解决你的问题,请参考以下文章

【linux c】子进程结束了,父进程还在,用ps -ef查看,子进程变成僵尸进程了。

unix下如何用ps命令得到进程的路径

linux 下查看进程用啥命令

linux 啥命令可以查看当前运行的进程

linux信号解释

linux 系统下oracle 10G perl进程cpu占用100% ,这个进程有啥用?能关掉吗?会不会有啥影响?