示例:
$ cat main.sh
#!/bin/bash
./child_level1.sh &
$ cat child_level1.sh
#!/bin/bash
./child_level2.sh &
$ cat child_level2.sh
#!/bin/bash
echo Hi, fork()s! &
$ ./main.sh # outputs Hi, fork()s
目标:编写一个运行$ 1的脚本 follow.sh 并收集所有分支的pids。像那样:
$ ./follow.sh ./main.sh
[pid_main.sh] [pid_child_level1.sh] [pid_child_level2.sh] [pid_of_echo]
该例子的4个数字)。这些数字可能会出现一段时间。也许有一个已知名称的实用程序 follow.sh ,如 pidtracer ?
答案 0 :(得分:1)
变量$!
给出了您在后台运行的最新命令的PID。因此,请在每个后台命令后立即尝试echo $!
。
答案 1 :(得分:1)
这是一个使用临时文件的简单解决方案,其名称存储在环境变量中:
$ cat main.sh
#!/bin/bash
export mytrace="pids-from-$$.tmp"
echo $$ >| "$mytrace"
./child_level1.sh &
$ cat child_level1.sh
#!/bin/bash
echo $$ >> "$mytrace"
./child_level2.sh &
$ cat child_level2.sh
#!/bin/bash
echo $$ >> "$mytrace"
echo -n "The pids are: "
tr \\n ' ' < "$mytrace"
echo
rm -f "$mytrace"
答案 2 :(得分:1)
感谢@tripleee。我认为这是一个很好的解决方案。
$ cat ./wrap_fork.c
//fork wrapper.c
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
pid_t fork(void){
FILE * f = fopen("/tmp/dearforks","a");
typedef pid_t (*t_fork)(void);
t_fork org_fork = dlsym(((void *) -1l), "fork");
pid_t p = org_fork();
fprintf(f,"pid = %i\n",p);
fclose(f);
return p;
}
$ gcc -fPIC -c -Wall wrap_fork.c
$ gcc -shared wrap_fork.o -ldl -lstdc++ -o wrap_fork.so
现在 follow.sh
$ cat follow.sh
#!/bin/bash
export LD_PRELOAD=./wrap_fork.so
$* &
现在,是时候执行了:
./follow.sh ./main.sh
结果:
$ cat /tmp/dearforks
pid = 2065
pid = 0
pid = 2066
pid = 0
pid = 2067
pid = 0
它有我想要的味道。除了一些零之外(和pids在将来调用 sleep 之后:)
为什么结果中有零?
答案 3 :(得分:0)
您将找不到所有pid,因为脚本退出的速度太快。如果运行时间足够长,可以使用
ps axo ppid,pid,comm
获取所有进程的父pid,脚本pid和命令名称。然后,您可以从第一个脚本pid $!
开始构建树。