1

例子:

$ 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

目标:编写一个脚本follow.sh,它运行 $1 并收集所有分叉的 pid。像那样:

$ ./follow.sh ./main.sh
[pid_main.sh] [pid_child_level1.sh] [pid_child_level2.sh] [pid_of_echo]

该示例为 4 个数字)。这些数字可能会在一段时间后出现。也许实用程序follow.sh有一个已知名称,例如pidtracer

4

4 回答 4

1

该变量$!给出了您在后台运行的最新命令的 PID。因此,请立即尝试echo $!执行每个后台命令。

于 2013-03-01T14:18:05.150 回答
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"
于 2013-03-01T17:08:13.570 回答
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

现在关注.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

它尝到了我想要的味道。除了一些零)(以及将来调用睡眠后的pid :(

为什么结果中有零

于 2013-03-04T18:12:35.903 回答
0

你不会找到所有的 pid,因为脚本退出太快了。如果它们运行的​​时间足够长,您可以使用

ps axo ppid,pid,comm

获取所有进程的父 pid、脚本 pid 和命令名称。然后,您可以从您的第一个脚本 pid 开始构建树$!

于 2013-03-01T14:37:07.310 回答