Jo Ja
Jo Ja

Reputation: 273

How to know all pids of forks in forks?

example:

$ 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

target: write a script follow.sh which runs $1 and collects pids of all forks. Like that:

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

4 numbers for that example). The numbers may appear since some time. Maybe there is a known name for utility follow.sh like pidtracer?

Upvotes: 1

Views: 536

Answers (4)

Jo Ja
Jo Ja

Reputation: 273

Thanks to @tripleee. I think it is a good solution.

$ 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

now follow.sh

$ cat follow.sh
#!/bin/bash
export LD_PRELOAD=./wrap_fork.so
$* &

now, it's time for execution:

./follow.sh ./main.sh

and the result:

$ cat /tmp/dearforks
pid = 2065
pid = 0
pid = 2066
pid = 0
pid = 2067
pid = 0

It's have a taste of what I want. Except some zeros) (And pids after calling sleep in future:( )

Why there are zeros in the result?

Upvotes: 1

Edouard Thiel
Edouard Thiel

Reputation: 6218

Here is a simple solution using a temporary file whose name is stored in an environment variable:

$ 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"

Upvotes: 1

Olaf Dietsche
Olaf Dietsche

Reputation: 74018

You won't find all the pids, because the scripts exit too fast. If they run long enough, you can use

ps axo ppid,pid,comm

to get the parent pid, script pid and command name of all processes. You can then build a tree starting from your first script pid $!.

Upvotes: 0

John Zwinck
John Zwinck

Reputation: 249133

The variable $! gives the PID of the most recent command you ran in the background. So try echo $! immediately following each background command.

Upvotes: 1

Related Questions