如何监控多个进程,如果一个进程结束,我想运行一些代码。
我找到了几个使用轮询来实现这个目的的例子,但我正在寻找一种方法来在进程死亡时推送(可能是由操作系统)。这可能用C或C ++吗?它应该在任何现代Linux上运行。
如果有机会,我想在不需要root权限的情况下这样做。
编辑:
整个计划的工作是监控这些流程并将此信息发送到另一台服务器,并将其集成到网站中。
我还没有开始这些流程,但我可以确保它们是以同一个用户身份启动的。
我认为它应该是可能的,因为Linux下的top / ps命令还为您提供了有关尚未启动的进程的信息。
答案 0 :(得分:4)
一般情况下,在Linux上,您无法通过waitpid(2)或SIGCHLD
- 请signal(7) - ...)通知非子进程或进程外的进程您的流程组或会话。
在某些Linux上,甚至可能不允许您(非根)进程查询其他进程是否存在。
当然,有/proc/
(每个进程有一个数字命名的目录,例如/proc/1234/
用于pid 1234的过程,请参阅proc(5))您可能会定期扫描(例如, readdir(3) ...)但是您无法收到有关更改的通知(请参阅inotify(7),其中无效对于/proc/
这样的伪文件系统...)在里面。请注意/proc/
是一个伪文件系统,访问它不涉及任何磁盘IO,所以非常快。
所以你可以做的是每隔几秒使用opendir(3),/proc/
,closedir(3),sleep(3)在循环中扫描readdir
。顺便说一句,从理论上讲,它不是防故障的(原则上,在实践中,内核可能会在几秒钟内重复使用相同的pid),并且可能无法捕获所有短期生存进程(例如ls
shell命令)。
/proc
的这种定期扫描很可能是top(1)实用程序正在做的事情。您可以通过深入了解top
的源代码或strace(1)来查看它。
如果您的C代码已经知道某个进程的pid并且只想检查该进程是否存在,那么它可以使用kill(2)和信号编号0。
另见systemd& credentials(7)
如果您可以更改受监控程序的代码或替换它们(例如,通过包装它们的小型C程序),情况就会大不相同;例如您可以将/usr/bin/foo
替换为/usr/local/bin/foo-wrapper
,并将foo-wrapper.c
编码为fork
- s& exec
- 原始的/usr/bin/foo
然后是waitpid(2),最后是send(2)或write(2)某些socket(7)或fifo(7)上的消息或pipe(7),并在显示器中使用基于poll(2)的event loop。如果您可以通过监视器获取所有程序fork
,那么事情也会有所不同(使用waitpid
...)。请参阅我的execicar.c计划获取灵感。
答案 1 :(得分:3)
您可以配置auditd
守护程序以在进程结束时创建审核记录(日志行)。然后使用auditd
监控inotify
日志文件。
前提是您可以访问auditd
配置及其日志文件。
答案 2 :(得分:-3)
请注意,/ proc /目录为每个正在运行的进程的PID保存一个目录 例如/ proc / 1是PID 1
在该目录下有cmdline文件,可用于确定PID的命令,即: cat / proc / 1 / cmdline / usr / lib中/ systemd / systemd
你可以遍历/ proc / [09] * irectories寻找与你正在寻找的匹配的cmdline,当你匹配该命令时,你可以简单地检查cmdline是否仍然匹配原始cmdline(同样的PID可以是用于另一个进程,如果它已终止
这是一段完成工作的简单代码: 我没有编写大部分错误纠正(如果找不到应用程序,程序崩溃,导致段错误的其他一些错误) #包括 #包括 #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");
}