추신 : 어떻게 주어진 pid에 대한 모든 자식 프로세스를 재귀 적으로 얻을 수 있습니까?


43

주어진 프로세스에 의해 생성 된 전체 프로세스 트리를 트리로 표시하고 해당 트리 만 다른 프로세스가없는 트리를 표시하려면 어떻게해야합니까?

출력은 예를 들어

 4378 ?        Ss     0:10 SCREEN
 4897 pts/16   Ss     0:00  \_ -/bin/bash
25667 pts/16   S+     0:00  |   \_ git diff
25669 pts/16   S+     0:00  |       \_ less -FRSX
11118 pts/32   Ss+    0:00  \_ -/bin/bash
11123 pts/32   S+     0:00      \_ vi

매개 변수를 사용하여 원하는 결과를 얻을 수 없었습니다 ps.

다음은 원하는 결과를 제공하지만 약간 관련된 것 같습니다.

#!/bin/bash

pidtree() {
  echo -n $1 " "
  for _child in $(ps -o pid --no-headers --ppid $1); do
    echo -n $_child `pidtree $_child` " "
  done
}

ps f `pidtree 4378`

누구나 더 쉬운 해결책이 있습니까?


대답은 아니지만로 시작하십시오 ps auxf.
jftuga

3
@jtfuga 이것은 실제로 내가 시작한 곳이지만 , 이것은 내가 원하지 않는 모든 프로세스를 제공합니다 .
kynan

답변:


37

이것은 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)

현재 프로세스의 세션 ID (SID)를 먼저 얻은 다음 해당 sid로 ps를 다시 호출합니다.

열 헤더가 필요하지 않은 경우 '-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각 자식 화면과 모든 손자 bash에 sid를 설정 하기 때문에 작동하지 않습니다 .

프로세스에 의해 생성 된 모든 프로세스를 얻으려면 전체 트리를 빌드해야합니다. 나는 그것을 위해 를 사용 했다. 처음에는 모두를 포함하는 해시 배열을 작성합니다 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

이것에 대한 문제는 (오래된 대답입니다) --forest 옵션은 Linux (또는 다른 gnu 기반 "ps"명령)에서만 작동합니다. Solaris와 MacOS는 그것을 좋아하지 않습니다.
Armand

@TrueY 당신은 그것을 할 수있는 C API에 대해 알고 있습니까? 감사합니다
Bionix1441

Bionix 아니요, 죄송합니다. 해당 트리를 빌드하기 위해 / proc / <PID> 디렉토리를 읽을 수 있습니다.
TrueY

1
psPID의 모든 자손을 필터링하는 필터 플래그 옵션이있는 경우 이것은 간단해야합니다 .
CMCDragonkai

26
pstree ${pid}

${pid}부모 프로세스의 pid는 어디에 있습니까 ?

젠투 리눅스에서는 pstree"psmisc"패키지에 있습니다.http://psmisc.sourceforge.net/


9
고마워, 내가 보았지만 pstree더 자세한 출력 형식을 놓쳤다 는 것을 언급해야 합니다. 그러나 pstree -p <pid>적어도 가까운 pid를 인쇄하십시오.
kynan

2
나도이 문제가있다, 나는 모든 자식 pid를 재귀 적으로 수집해야하지만 pid 만 필요하므로 sed모든 것을해야합니다 .. mmm 작동 :)pstree -pn 4008 |grep -o "([[:digit:]]*)" |grep -o "[[:digit:]]*"
Aquarius Power

12

다음은 즉시 실행되는 버전입니다 ( ps한 번만 실행되었으므로). bash 및 zsh에서 작동합니다.

pidtree() (
    [ -n "$ZSH_VERSION"  ] && setopt shwordsplit
    declare -A CHILDS
    while read P PP;do
        CHILDS[$PP]+=" $P"
    done < <(ps -e -o pid= -o ppid=)

    walk() {
        echo $1
        for i in ${CHILDS[$1]};do
            walk $i
        done
    }

    for i in "$@";do
        walk $i
    done
)

1
또한 현재 프로세스의 pid를 인쇄합니다. 원하는 프로세스는 원하지 않을 수도 있습니다. 현재 프로세스가 나열되지 않기를 원하므로 (현재 프로세스의 자손) echo $1첫 번째 for 루프 내부 로 이동하여로 변경하여 스크립트를 변경했습니다 echo $i.
Mark Lakata

1
나는 이것을 발견했을 때 그런 함수를 작성하려고했습니다. 이것은 MacOS, Linux 및 Solaris에서 작동하는 유일한 솔루션입니다. 훌륭한 일. ps의 단일 실행에 의존하여 작업을 메모리에서 수행하는 것을 좋아하십시오.
Armand

3

부모의 자식 프로세스 목록 pid를 만들기 위해 작은 bash 스크립트를 만들었습니다. 자식이없는 마지막 자식 프로세스를 찾을 때까지 재귀 적으로. 트리 뷰를 제공하지 않습니다. 그것은 단지 모든 pid를 나열합니다.

function list_offspring {
  tp=`pgrep -P $1`          #get childs pids of parent pid
  for i in $tp; do          #loop through childs
    if [ -z $i ]; then      #check if empty list
      exit                  #if empty: exit
    else                    #else
      echo -n "$i "         #print childs pid
      list_offspring $i     #call list_offspring again with child pid as the parent
    fi;
  done
}
list_offspring $1

list_offspring의 첫 번째 인수는 부모 pid입니다


1
질문 자체의 트리를 포함하여 실제 트리를 인쇄하지 않는 bash 스크립트를 제공하는 다른 답변이 이미 있습니다. 귀하의 (부분) 답변이 기존 (부분) 답변보다 어떤 장점이 있습니까?
David Richerby 2016 년

재귀를 사용하고 설명을 추가했습니다. 누군가에게 도움이 될 것이라고 생각했습니다. 제목이 요구하는대로 정확하게 수행합니다.
Merijn

ps는 유닉스 변형에 따라 다를 수 있기 때문에 pgrep 사용을 좋아합니다.
존 Szakmeister

3

ps -H -g "$pid" -o comm

트리 자체를 추가하지 않고 프로세스 목록 일뿐입니다.

예를 들어

COMMAND
bash
  nvim
    python

-H옵션은 프로세스 트리 또는 "프로세스 계층 (포리스트)"
Anthony G-Monica에 대한 정의

2

나는 똑같은 문제에 대한 해결책을 찾기 위해 노력하고 있습니다. 기본적으로 ps 맨 페이지에는 단일 명령으로 원하는 것을 수행 할 수있는 옵션이 문서화되어 있지 않습니다. 결론 : 스크립트가 필요합니다.

나는 당신과 매우 비슷한 스크립트를 생각해 냈습니다. ~ / .bashrc에 붙여 넣기 때문에 어떤 쉘에서도 사용할 수 있습니다.

pidtree() {
  local parent=$1
  local list=
  while [ "$parent" ] ; do     
    if [ -n "$list" ] ; then
      list="$list,$parent"
    else
      list="$parent"
    fi
    parent=$(ps --ppid $parent -o pid h)
  done
  ps -f -p $list f
}

1

명령 행에서 :

ps -o time,pid,ppid,cmd --forest -g -p $(pgrep -x bash)

출력 :

    TIME   PID  PPID CMD
00:00:00  5484  5480 bash
00:00:01  5531  5484  \_ emacs -nw .bashrc
00:00:01  2986  2984 /bin/bash
00:00:00  4731  2986  \_ redshift
00:00:00  5543  2986  \_ ps -o time,pid,ppid,cmd --forest -g -p 2986 5484

더 우아한 방법은 다음에서 함수를 정의하는 것입니다 .bashrc.

function subps()                                                                                    
{                                                                                                   
    process=$(pgrep -x $1)                                                                                                                                                                     
    ps -o time,pid,ppid,cmd --forest -g -p $process                                                 
}    

그런 다음 명령 행에서 실행하십시오.

subps bash

1

이것은 한 줄에 각각 pid + child pid 만 제공하므로 추가 처리에 유용합니다.

pidtree() {
    for _pid in "$@"; do
        echo $_pid
        pidtree `ps --ppid $_pid -o pid h`
    done
}

0

필립의 위를 기반으로 비슷한 스크립트를 만들었습니다.

pidlist() {
local thispid=$1
local fulllist=
local childlist=
childlist=$(ps --ppid $thispid -o pid h)
for pid in $childlist
do
  fulllist="$(pidlist $pid) $fulllist"
done
echo "$thispid $fulllist"
}

이것은 모든 자식, 손자 등 pid를 공백으로 구분 된 형식으로 출력합니다. 이것은 다음과 같이 ps에 공급 될 수 있습니다.

ps -p $ (pidlist pid )


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.