如何知道叉子中的所有叉子?

时间:2013-03-01 14:00:15

标签: bash process fork execve

示例:

$ 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

4 个答案:

答案 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 $!开始构建树。