Це pstree
дуже хороше рішення, але воно трохи стримане. Я використовую ps --forest
замість цього. Але не для PID
( -p
), оскільки він друкує лише конкретний процес, а для сеансу ( -g
). Він може роздрукувати будь-яку інформацію, ps
може надрукувати у вишуканому дереві мистецтв ASCII, що визначає -o
параметр.
Тож моя пропозиція щодо цієї проблеми:
ps --forest -o pid,tty,stat,time,cmd -g 2795
Якщо процес не є лідером сеансу, слід застосувати трохи більше фокусу:
ps --forest -o pid,tty,stat,time,cmd -g $(ps -o sid= -p 2795)
Це спочатку отримує ідентифікатор сеансу (SID) поточного процесу, а потім знову викликає ps із цим sid.
Якщо заголовки стовпців не потрібні, додайте '=' після кожного визначення стовпця в параметрах '-o', наприклад:
ps --forest -o pid=,tty=,stat=,time=,cmd= -g $(ps -o sid= -p 2795)
Приклад запуску та результат:
$ 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
На жаль, це не спрацьовує, screen
оскільки це встановлює сторону для екрану кожної дитини та всіх онуків.
Щоб усі процеси були породжені процесом, потрібно створити все дерево. Я використовував awk для цього. Спочатку він будує хеш-масив, щоб містити всіх PID => ,child,child...
. Наприкінці він закликає рекурсивну функцію для вилучення всіх дочірніх процесів певного процесу. Результат передається іншому ps
для форматування результату. Справжній PID повинен бути записаний як аргумент для пробудження замість <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)}')
Для SCREEN-процесу (pid = 8041) приклад виводу виглядає так:
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
.