Как узнать все пиды форков в форках?

пример:

$ 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 и собирает идентификаторы всех форков. Как это:

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

4 числа для этого примера). Цифры могут появиться с некоторого времени. Может быть, есть известное название утилиты follow.sh, например pidtracer?


person Jo Ja    schedule 01.03.2013    source источник
comment
Это домашнее задание? Вывод из ps содержит информацию об идентификаторе родительского процесса, или, если вас устраивает решение только для Linux, вы можете получить к нему доступ в машиночитаемой форме из файловой системы /proc.   -  person tripleee    schedule 01.03.2013
comment
Нисколько. Это не домашнее задание.   -  person Jo Ja    schedule 01.03.2013
comment
Пример, когда такое решение (с =~ pstree) не работает: ($ main.sh &) (это create =› main.sh-+-child_level1.sh-+-child_level2.sh) (затем killall -r level1 ) (main.sh и child_level2.sh не связаны с PPID)   -  person Jo Ja    schedule 01.03.2013
comment
Вы можете strace -f main.sh искать fork в выводе или, возможно, создать простую оболочку LD_PRELOAD для печати каждого PID после fork()ing.   -  person tripleee    schedule 03.03.2013


Ответы (4)


Переменная $! дает PID самой последней команды, которую вы запускали в фоновом режиме. Так что попробуйте echo $! сразу после каждой фоновой команды.

person John Zwinck    schedule 01.03.2013
comment
в след.ш $! возвращает только pid для main.sh&, а нам нужны pid для child1, child2 и echo - person Jo Ja; 01.03.2013
comment
@JoJa Итак, вы хотите всех братьев и сестер main.sh? - person Kevin; 01.03.2013
comment
@JoJa: правильно, поэтому вам нужно возвращать PID на каждом уровне. Эхо, печать в файл, что-нибудь. - person John Zwinck; 02.03.2013

Вот простое решение с использованием временного файла, имя которого хранится в переменной среды:

$ 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"
person Edouard Thiel    schedule 01.03.2013
comment
В своей истории я ничего не могу изменить, кроме follow.sh. На самом деле некоторые из них очень длинные файлы bash и другие файлы .bin) - person Jo Ja; 04.03.2013

Спасибо @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 в будущем:()

Почему в результате нули?

person Jo Ja    schedule 04.03.2013

Вы не найдете все pids, потому что скрипты завершаются слишком быстро. Если они работают достаточно долго, вы можете использовать

ps axo ppid,pid,comm

чтобы получить родительский pid, pid скрипта и имя команды всех процессов. Затем вы можете построить дерево, начиная с вашего первого скрипта pid $!.

person Olaf Dietsche    schedule 01.03.2013
comment
если кто-то убил (или разбил) child_level1, тогда ppid child_level2 будет установлен в 1. Я думаю, нам нужно что-то вроде strace -f - person Jo Ja; 01.03.2013
comment
@JoJa Правильно, вот почему я сказал, Если они будут работать достаточно долго! - person Olaf Dietsche; 01.03.2013