简体   繁体   English

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

[英]How to get notified when a process ends under linux?

How do I monitor a number of processes and if one process ends, I would like to run some code. 如何监控多个进程,如果一个进程结束,我想运行一些代码。

I have found several examples which used polling to achieve this but I am looking for a method to get pushed (probably by the OS) when a process dies. 我找到了几个使用轮询来实现这一目的的例子,但是我正在寻找一种方法来在进程死亡时被推送(可能是由操作系统)。 Is this possible with C or C++? 这可能用C或C ++吗? It should run on any modern Linux. 它应该在任何现代Linux上运行。

If there is any chance, I would like to do that without needing root privileges. 如果有机会,我想在不需要root权限的情况下这样做。

EDIT: 编辑:

The job of this whole program is to monitor these processes and send this information to another server where it gets integrated into a website. 整个计划的工作是监控这些流程并将此信息发送到另一台服务器,并将其集成到网站中。

I have not started these processes but I could ensure that they are started as the same user. 我还没有启动这些进程,但我可以确保它们是作为同一个用户启动的。

I thought it should be possible because the top / ps command under Linux also gives you information about processes you haven't started. 我认为它应该是可能的,因为Linux下的top / ps命令也为您提供了有关尚未启动的进程的信息。

In general on Linux you can't be notified (with waitpid(2) or SIGCHLD -see signal(7) - ...) about non-child processes, or processes outside of your process group or session. 通常在Linux上,您无法通过waitpid(2)SIGCHLD -see signal(7) - ...)通知非子进程或进程组或会话之外的进程。

And on some Linux your (non-root) process might not even be allowed to query the existence of other processes. 在某些Linux上,甚至可能不允许您的(非根)进程查询其他进程的存在。

Of course, there is /proc/ (having one numerical-named directory per process, eg /proc/1234/ for process of pid 1234, see proc(5) ) that you might regularly scan (eg with readdir(3) ...) but you cannot be notified (see inotify(7) , which does not work for pseudo-file systems like /proc/ ...) about changes inside it. 当然, /proc/ (每个进程有一个数字命名的目录,例如/proc/1234/用于pid 1234的进程,参见proc(5) ),你可以定期扫描(例如用readdir(3) .. 。)但是你不能得到通知(参见inotify(7) ,这对于像/proc/ ...这样的伪文件系统不起作用 )。 Notice that /proc/ is a pseudo file system, and accessing it does not involve any disk IO so is quite quick. 请注意/proc/是一个伪文件系统,访问它不涉及任何磁盘IO,所以非常快。

So what you could do is scan /proc/ every few seconds using opendir(3) , readdir , closedir(3) , sleep(3) in a loop. 所以你可以做的是使用opendir(3)readdirclosedir(3)sleep(3)在循环中每隔几秒扫描/proc/ BTW, that in theory is not fail-proof (in principle, not in practice, the kernel might reuse the same pid within a few seconds), and probably won't catch all short-living processes (such as ls shell commands). 顺便说一下,理论上它不是防故障的(原则上,在实践中,内核可能在几秒钟内重用相同的pid),并且可能不会捕获所有短生命进程(例如ls shell命令)。

Such a periodic scan of /proc is very probably what the top(1) utility is doing. /proc这种周期性扫描很可能是top(1)实用程序正在做的事情。 You could check that by diving into the source code of top or by strace(1) -ing it. 您可以通过深入了解top的源代码或通过strace(1)来检查它。

If your C code knows already the pid of some process and simply wants to check the existence of that process, it can use kill(2) with a signal number 0. 如果你的C代码已经知道某个进程的pid并且只想检查该进程是否存在,那么它可以使用带有信号编号0的kill(2)

See also systemd & credentials(7) . 另请参见systemdcredentials(7)

If you can change the code of the monitored programs or replace them (eg by your small C program wrapping them) things are very different; 如果您可以更改受监控程序的代码或替换它们(例如,通过包装它们的小C程序),情况就会大不相同; eg you could replace /usr/bin/foo with /usr/local/bin/foo-wrapper and code a foo-wrapper.c which fork -s & exec -s the original /usr/bin/foo then waitpid(2) on it and finally send(2) or write(2) some message on some socket(7) or fifo(7) or pipe(7) , and use a poll(2) based event loop in your monitor. 例如,您可以用/usr/local/bin/foo-wrapper替换/usr/bin/foo并编写一个foo-wrapper.c ,其中fork -s& exec -s原始的/usr/bin/foo然后waitpid(2)在它上面,最后在某个socket(7)fifo(7)pipe(7)发送(2)写入(2)某些消息,并在监视器中使用基于poll(2)事件循环 If you can get all the programs fork -ed by your monitor things are also different (use waitpid ...). 如果你能得到的所有程序fork了您的显示器事情-ed也不同(使用waitpid ...)。 See my execicar.c program for inspiration. 请参阅我的execicar.c计划获取灵感。

You can configure auditd daemon to create audit records (log lines) when a process ends. 您可以配置auditd守护程序以在进程结束时创建审核记录(日志行)。 And then monitor auditd log file with inotify . 然后使用inotify监视auditd日志文件。

Provided you have access to auditd configuration and its log file. 只要您可以访问auditd配置及其日志文件。

note that the /proc/ directory holds a directory for each running process' PID for example /proc/1 is PID 1 请注意/ proc /目录为每个正在运行的进程保存一个目录'PID例如/ proc / 1是PID 1

under that directory there's the cmdline file which can be used to determine the PID's command, ie: cat /proc/1/cmdline /usr/lib/systemd/systemd 在该目录下有cmdline文件,可用于确定PID的命令,即:cat / proc / 1 / cmdline / usr / lib / systemd / systemd

you can traverse the /proc/[09]* irectories looking for a cmdline that matches what you are looking for, when you match that command you can simply check if the cmdline still matches the original one(the same PID can be used for another process if it had terminated 您可以遍历/ proc / [09] * irectories寻找与您要查找的cmdline相匹配的cmdline,当您匹配该命令时,您只需检查cmdline是否仍然与原始cmdline匹配(相同的PID可用于另一个过程如果已经终止

here's a simple piece of code that gets that job done: I haven't written most of the error correction(program crashes if the application isn't found, some other errors that cause segfault) #include #include #include 这是一段完成工作的简单代码:我没有编写大部分错误纠正(如果找不到应用程序,程序崩溃,导致段错误的其他一些错误)#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");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM