bash 쉘 스크립트에서 하위 프로세스의 PID를 상위 프로세스로 가져오는 방법은 무엇입니까?

bash 쉘 스크립트에서 하위 프로세스의 PID를 상위 프로세스로 가져오는 방법은 무엇입니까?

내 쉘 스크립트는 다음과 같습니다.

#!/bin/bash
./process1 #It will create a sub process: sub_process1
while [ condition ]; do
    break
done
kill -9 process1 and sub_process1

내 스크립트에서는 process1이라는 프로세스를 생성합니다. process1은 하위 프로세스 sub_process1을 생성합니다.
스크립트가 완료되기 전에 Process1 및 sub_process1을 종료해야 합니다.
process1을 종료하는 것은 PID를 파일에 기록하기 때문에 쉽습니다. 그러나 sub_process1은 그렇지 않습니다. sub_process1은 타사 구성 요소이므로 소스 코드를 건드릴 수 없습니다.
sub_process1의 PID를 얻는 솔루션이 있습니다.

  1. 모든 프로세스를 열거하려면 이 명령을 사용하십시오 ps aux.
  2. 명령을 사용하여 각 프로세스의 PPID(상위 프로세스 ID)를 가져옵니다 ps -f [PID]. PPID가 process1의 PID와 동일한 경우 프로세스는 sub_process1이어야 합니다.
    위의 솔루션은 약간 복잡합니다. 하위 프로세스 ID를 얻는 간단한 솔루션이 있습니까?
    감사합니다.

답변1

pgrepLinux: / 로 표시했으므로 pkill다음과 같이 하세요.

PID_OF_SUB_PROCESS1=$( pgrep -P $PID_OF_PROCESS1 )
pkill -P $PID_OF_PROCESS1

답변2

process백그라운드 프로세스로 실행하여 프로세스 ID를 얻을 수 있습니다.

./process1 &
pid1=$!
wait "$pid1"

명령 은 원래 스크립트와 마찬가지로 종료를 wait기다립니다 (자식 프로세스는 아님). process1원래 스크립트에는 process1마지막에 종료할 것이 없습니다. ./process1명령은 process1종료 시에만 완료됩니다. 프로세스에는 동일한 이름을 가진 하위 프로세스가 있을 수 있습니다(즉, 프로그램이fork하지만execve). process1스크립트가 시작된 직후에 스크립트를 계속 실행 하려면 이 wait줄을 생략하세요.

당신이 가지고 있다면pkill명령은 프로세스의 모든 하위 프로세스를 종료하는 편리한 방법입니다. 프로세스가 여전히 실행 중이어야 합니다.좀비그렇지 않으면 하위 프로세스의 상위 프로세스 ID가 1로 재설정되어 더 이상 그런 방식으로 추적할 수 없습니다. 백그라운드 프로세스 ID는 wait스크립트에서 호출 하지 않는 한 유효한 상태로 유지됩니다.

./process1 &
pid1=$!
pkill -9 -P "$pid1"
kill -9 "$pid1"

프로세스와 그 자식, 그 자식을 재귀적으로 추적하는 또 다른 방법은 다음과 같습니다.프로세스 그룹. 프로세스의 하위 항목은 명시적으로 변경하지 않는 한 동일한 프로세스 그룹을 갖습니다. Linux에서는 다음을 사용할 수 있습니다.setsid이 명령은 자체 프로세스 그룹에서 프로그램을 실행합니다. 프로세스 그룹은 원래 프로세스의 프로세스 ID로 식별됩니다. 프로세스 그룹의 모든 프로세스를 종료하려면 프로세스 그룹 ID에 음수를 전달하십시오 kill.

setsid ./process1 &
pgid1=$!
kill -9 "-$pgid1"

프로세스를 추적하는 또 다른 방법은 프로세스가 파일을 열도록 하는 것입니다. 이 방법은 프로세스가 파일을 닫지 않는 한 작동하므로 데몬으로 실행하려는 프로그램에는 적합하지 않을 수 있습니다. 명령 사용fuser파일이 열려 있는 프로세스를 종료합니다.

tmpfile=$(mktemp)
process1 <"$tmpfile"
fuser -k -9 "$tmpfile"

답변3

네가 할 수 있는 건 kill -TERM너 뿐이야프로세스 그룹. 스크립트가 셸에서 호출되면 스크립트의 PID와 동일한 자체 프로세스 그룹을 갖게 됩니다.

kill -TERM -$$

다르게 호출되면 프로세스 그룹 ID가 PID와 같지 않을 수 있습니다.

kill -TERM -`ps -o pgid $$ | tail -1`

kill -9프로그램에 공정한 기회를 제공하지 않는 한 스크립트나 프로그램에 참여해서는 안 됩니다 kill -TERM.

a를 실행하는 find pid and kill it것은 경쟁 조건의 영향을 받습니다(비록 상자가 미친 프로세스를 생성하지 않는 한 자주 보여주지는 않지만). pid당신이 죽이는 pid가 당신의 아이이고 pid가 기다리지 않음으로써 재활용되지 않을 것이라고 보장하지 않는 한 s는 움직이는 목표입니다. (내가 아는 한 bash에서는 거의 할 수 없습니다) 그렇지 않으면 당신은 될 수 없습니다 올바른 프로세스를 종료하고 있음을 100% 확신합니다(pid를 찾아 종료하는 사이에 프로세스가 종료되고 다른 프로세스가 pid를 획득했을 수 있습니다).

답변4

setsid ./process1 & pgid=$!다음을 사용하여 별도의 프로세스 그룹을 사용하거나 생성해야 합니다.직업 통제: set -m; ./process1 & pgid=$!; set +m그런 다음 다음과 같이 전체 프로세스 그룹을 종료합니다 kill -- -$pgid. 추가 정보여기

관련 정보