우아하게 하위 프로세스 목록을 얻습니다. $pid | tr “\n” ” ” |sed

에서 내려 오는 모든 프로세스 (예 : 어린이, 손자 등) 목록을 얻고 싶습니다 $pid. 이것이 내가 생각해 낸 가장 간단한 방법입니다.

pstree -p $pid | tr "\n" " " |sed "s/[^0-9]/ /g" |sed "s/\s\s*/ /g"

모든 하위 프로세스 의 전체 목록을 가져 오는 명령이나 간단한 방법이 있습니까?



답변

다음은 다소 단순하며 명령 이름에서 숫자를 무시하는 이점이 있습니다.

pstree -p $pid | grep -o '([0-9]\+)' | grep -o '[0-9]\+'

또는 Perl과 함께 :

pstree -p $pid | perl -ne 'print "$1\n" while /\((\d+)\)/g'

우리는 괄호 안의 숫자를 찾고 있으므로 예를 들어 2를 자식 프로세스로 제공하지 않습니다 gif2png(3012). 그러나 명령 이름에 괄호 안에 숫자가 있으면 모든 베팅이 해제 된 것입니다. 지금까지는 텍스트 처리 만 가능합니다.

또한 프로세스 그룹이 갈 길이라고 생각합니다. 자체 프로세스 그룹에서 프로세스를 실행하려면 데비안 패키지 ‘daemontools’에서 ‘pgrphack’도구를 사용할 수 있습니다.

pgrphack my_command args

또는 다시 Perl을 켤 수 있습니다.

perl -e 'setpgid or die; exec { $ARGV[0] } @ARGV;' my_command args

여기서 유일하게주의해야 할 점은 프로세스 그룹이 중첩되지 않기 때문에 일부 프로세스가 자체 프로세스 그룹을 작성하는 경우 해당 하위 프로세스는 더 이상 사용자가 작성한 그룹에 속하지 않는 것입니다.


답변

descendent_pids() {
    pids=$(pgrep -P $1)
    echo $pids
    for pid in $pids; do
        descendent_pids $pid
    done
}

답변

내가 찾은 가장 짧은 버전은 pop3d다음 과 같은 명령을 올바르게 처리합니다 .

pstree -p $pid | perl -ne 's/\((\d+)\)/print " $1"/ge'

다음과 같은 이상한 이름을 가진 명령이 있으면 잘못 처리됩니다 my(23)prog.


답변

정확성 문제도 있습니다. 결과를 순진하게 파싱하는 pstree것은 여러 가지 이유로 문제가 있습니다.

  • pstree는 PID 스레드 ID를 표시합니다 (이름은 중괄호로 표시됨)
  • 명령 이름에는 중괄호, 괄호 안의 숫자를 포함하여 안정적인 구문 분석이 불가능할 수 있습니다.

Python과 psutil패키지가 설치되어있는 경우이 스 니펫을 사용하여 모든 하위 프로세스를 나열 할 수 있습니다.

pid=2235; python3 -c "import psutil
for c in psutil.Process($pid).children(True):
  print(c.pid)"

(예를 들어 psutil 패키지는 tracerFedora / CentOS에서 사용 가능한 명령 의 종속성으로 설치됩니다 .)

또는 Bourne 쉘에서 프로세스 트리의 너비 우선 탐색을 수행 할 수 있습니다.

ps=2235; while [ "$ps" ]; do echo $ps; ps=$(echo $ps | xargs -n1 pgrep -P); \
  done | tail -n +2 | tr " " "\n"

pid의 전이 폐쇄를 계산하기 위해, 꼬리 부분은 생략 될 수있다.

위의 내용은 재귀를 사용하지 않으며 ksh-88에서도 실행됩니다.

Linux에서는 pgrep호출을 제거 하고 대신 다음 정보를 읽을 수 있습니다 /proc.

ps=2235; while [ "$ps" ]; do echo $ps ; \
  ps=$(for p in $ps; do cat /proc/$p/task/$p/children; done); done \
  | tr " " "\n"' | tail -n +2

각 PID 당 하나의 포크 / 실행을 저장 pgrep하고 각 호출에서 추가 작업을 수행하기 때문에보다 효율적 입니다.


답변

이 Linux 버전에는 / proc 및 ps 만 필요합니다. @maxschlepzig의 훌륭한 답변 의 마지막 부분에서 수정되었습니다 . 이 버전은 루프에서 하위 프로세스를 생성하는 대신 셸에서 직접 / proc를 읽습니다. 이 글타래 제목이 요청하는 것처럼 조금 빠르며 약간 더 우아합니다.

#!/bin/dash

# Print all descendant pids of process pid $1
# adapted from /unix//a/339071

ps=${1:-1}
while [ "$ps" ]; do
  echo $ps
  unset ps1 ps2
  for p in $ps; do
    read ps2 < /proc/$p/task/$p/children 2>/dev/null
    ps1="$ps1 $ps2"
  done
  ps=$ps1
done | tr " " "\n" | tail -n +2

답변

두 가지 (아주 인공적인) 유스 케이스 각각에서 왜 불행한 프로세스의 하위 프로세스를 죽이고 싶습니까? 자녀가 살거나 죽어야하는 과정보다 어떻게 더 잘 아십니까? 이것은 나에게 나쁜 디자인처럼 보입니다. 프로세스 자체가 정리되어야합니다.

당신이 정말로 더 잘 알고 있다면, 당신은이 서브 프로세스들을 분기시켜야하고, ‘데몬 화 된 프로세스’는 믿을 수 없을 정도로 너무 멍청합니다 fork(2).

예를 들어 @Gilles에서 제안한대로 하위 프로세스를 별도의 프로세스 그룹에 두는 등 프로세스 트리를 통해 하위 프로세스 목록을 유지하거나 그루 빙하는 것을 피해야합니다.

어쨌든, 나는 당신의 데몬 처리 된 프로세스가 깊은 서브 서브 서브 프로세스 트리보다 작업자 스레드 풀 (포함 프로세스와 함께 죽는)을 만드는 것이 낫다고 생각합니다. .


답변

다음은 pgrep을 사용하고 동시에 모든 하위 항목을 가져올 수있는 pgrep 래퍼 스크립트입니다.

~/bin/pgrep_wrapper:

#!/bin/bash

# the delimiter argument must be the first arg, otherwise it is ignored
delim=$'\n'
if [ "$1" == "-d" ]; then
    delim=$2
    shift 2
fi

pids=
newpids=$(pgrep "$@")
status=$?
if [ $status -ne 0 ]; then
    exit $status
fi

while [ "$pids" != "$newpids" ]; do
    pids=$newpids
    newpids=$( { echo "$pids"; pgrep -P "$(echo -n "$pids" | tr -cs '[:digit:]' ',')"; } | sort -u )
done
if [ "$delim" != $'\n' ]; then
    first=1
    for pid in $pids; do
        if [ $first -ne 1 ]; then
            echo -n "$delim"
        else
            first=0
        fi
        echo -n "$pid"
    done
else
    echo "$pids"
fi

pgrep_recursive -U $USER java현재 사용자로부터 모든 Java 프로세스 및 하위 프로세스를 찾는 것과 같은 일반적인 pgrep을 호출하는 것과 같은 방식으로 호출하십시오 .