To pstree
bardzo dobre rozwiązanie, ale jest trochę powściągliwe. Używam ps --forest
zamiast tego. Ale nie dla a PID
( -p
), ponieważ drukuje tylko określony proces, ale dla session ( -g
). Może wydrukować dowolną informację, którą ps
można wydrukować w fantazyjnym drzewie graficznym ASCII określającym -o
opcję.
Więc moja sugestia dotycząca tego problemu:
ps --forest -o pid,tty,stat,time,cmd -g 2795
Jeśli proces nie jest liderem sesji, należy zastosować nieco więcej sztuczki:
ps --forest -o pid,tty,stat,time,cmd -g $(ps -o sid= -p 2795)
Najpierw pobiera identyfikator sesji (SID) bieżącego procesu, a następnie ponownie wywołuje ps z tym identyfikatorem sid.
Jeśli nagłówki kolumn nie są potrzebne, dodaj „=” po każdej definicji kolumny w opcjach „-o”, takich jak:
ps --forest -o pid=,tty=,stat=,time=,cmd= -g $(ps -o sid= -p 2795)
Przykładowy przebieg i wynik:
$ ps --forest -o pid=,tty=,stat=,time=,cmd= -g $(ps -o sid= -p 30085)
27950 pts/36 Ss 00:00:00 -bash
30085 pts/36 S+ 00:00:00 \_ /bin/bash ./loop.sh
31888 pts/36 S+ 00:00:00 \_ sleep 5
Niestety to nie działa, screen
ponieważ ustawia sid dla każdego ekranu potomnego i wszystkich bashów wnuka.
Aby wszystkie procesy zostały odrodzone przez proces, należy zbudować całe drzewo. Użyłem do tego awk . Najpierw buduje tablicę skrótów, która zawiera wszystko PID => ,child,child...
. Na koniec wywołuje funkcję rekurencyjną, aby wyodrębnić wszystkie procesy potomne danego procesu. Wynik jest przekazywany do innego w ps
celu sformatowania wyniku. Rzeczywisty PID musi być zapisany jako argument do awk zamiast <PID>
:
ps --forest $(ps -e --no-header -o pid,ppid|awk -vp=<PID> 'function r(s){print s;s=a[s];while(s){sub(",","",s);t=s;sub(",.*","",t);sub("[0-9]+","",s);r(t)}}{a[$2]=a[$2]","$1}END{r(p)}')
W przypadku procesu SCREEN (pid = 8041) przykładowe dane wyjściowe wyglądają następująco:
PID TTY STAT TIME COMMAND
8041 ? Ss 0:00 SCREEN
8042 pts/8 Ss 0:00 \_ /bin/bash
8092 pts/8 T 0:00 \_ vim test_arg test_server
12473 pts/8 T 0:00 \_ vim
12972 pts/8 T 0:00 \_ vim
ps auxf
.