bash의 작업 제어를 사용하여 EXIT를 포착하고 종료하세요.

bash의 작업 제어를 사용하여 EXIT를 포착하고 종료하세요.

여러 프로그램을 실행하는 bash 스크립트가 있습니다

#!/bin/sh
python program1.py &
python program2.py &
other programs ... &
lastProgram

나는 그것을 다음과 같이 실행한다../myscript.sh

Ctrl+를 눌러 닫으면 C종료 lastProgram되고 다른 모든 프로그램은 백그라운드에서 계속 실행됩니다. 문제는 다른 프로그램을 종료해야 한다는 점이다.

스크립트에서 시작된 모든 프로그램의 종료를 올바르게 처리하는 방법은 무엇입니까?

답변1

종료 시 프로세스 ID를 수집하고 백그라운드 프로세스를 종료합니다.

#!/bin/bash
killbg() {
        for p in "${pids[@]}" ; do
                kill "$p";
        done
}
trap killbg EXIT
pids=()
background job 1 & 
pids+=($!)
background job 2... & 
pids+=($!)
foreground job

EXIT이유에 관계없이 캡처는 셸이 종료될 때 함수를 실행합니다. trap killbg SIGINT에서만 변경할 수 있습니다 ^C.

스크립트가 시작을 시도하기 전에 백그라운드 프로세스 중 하나가 종료되었는지 확인하지 않습니다. 이렇게 하면 실수를 할 수도 있고, 더 심한 경우 잘못된 공정을 촬영하게 될 수도 있습니다.


아니면 직업 ID로 그들을 죽이세요. 출력을 읽고 jobs어떤 것이 아직 활성 상태인지 알아 보겠습니다.

#!/bin/bash 
killjobs() {
    for x in $(jobs | awk -F '[][]' '{print $2}' ) ; do 
        kill %$x
    done
}
trap killjobs EXIT
sleep 999 &
sleep 1 &
sleep 999 &
sleep 30

다른 프로세스(예: subshell: )를 생성하는 백그라운드 프로세스를 실행하는 경우 이 프로세스가 제대로 작동하려면 ("모니터 모드")를 사용하여 작업 제어를 활성화 (sleep 1234 ; echo foo) &해야 합니다 . set -m그렇지 않으면 부팅 프로세스만 종료됩니다.

답변2

방금 PID 수집에 대한 비슷한 질문을 읽었고 스크립트 끝에서 PID를 종료했습니다.질문완료된 프로세스의 PID입니다.새로운 공정에서 재활용 및 재사용 가능스크립트가 완료되기 전에 다음을 수행할 수 있습니다.새로운 (임의) 프로세스 종료.

bash의 작업 제어를 사용하여 EXIT를 포착하고 종료하세요.

bash의 작업 제어를 사용하면 트랩과 %n jobspec을 사용하여 스크립트에서 시작된 프로세스만 종료하여 실행할 수 있는 최대 작업 수를 계산할 수 있습니다(이 예에서는 3개만).

#!/bin/bash
#trap 'kill %1 %2 %3' 0     # 0 or EXIT are equivalent
#trap 'kill %1 %2 %3' EXIT  # or use {1..n} as below
trap 'kill %{1..3}' EXIT
sleep 33 &
sleep 33 &
sleep 33 &
echo processes are running, ctrl-c the next sleep
sleep 66
echo this line will never be executed

이미 완료된 존재하지 않는 작업 사양을 추가로 "종료"하면 오류 메시지만 나타날 뿐 다른 새로운/무작위 프로세스는 종료되지 않습니다.


스크립트의 전체 프로세스 그룹을 종료합니다.

이는 스크립트의 전체 프로세스 그룹을 종료하는 약간 다른 방법입니다. 그러나 스크립트/셸의 작업 제어가 설정되지 않은 경우할 수 있다상위로부터 PPID를 상속받습니다. 하지만 작업 제어가 없으면 위의 작업도 작동하지 않습니다.

차이점은 트랩의 kill 명령이 bash의 PID를 사용한다는 것입니다. 이는 새 프로세스의 PGID가 되기 때문입니다.

trap 'kill -- -$$' EXIT

바라보다이 관련 질문또는여기서 Johannes는 Ziemke를 "낚아채서" SIGINT 및 SIGTERM을 캡처하고 setsid"자살 위험이 없도록 새 프로세스 그룹에서 전체 프로세스 그룹을 종료합니다.".)

답변3

실행이 완료되기 전에 완료되지 않은 모든 백그라운드 프로세스를 종료하려면 lastProgram모든 PID를 저장해야 합니다.

python program1.py &
p1pid=$!
python program2.py &
p2pid=$!
other programs ... &
p3pid=$!
lastProgram

kill $p1pid $p2pid $p3pid

wait스크립트를 종료하기 전에 모든 백그라운드 프로세스의 실행이 완료될 때까지 기다리려는 경우 이 명령을 사용할 수 있습니다 .

python program1.py &
python program2.py &
other programs ... &
lastProgram
wait

답변4

이것은 내 한 줄 명령입니다( bash).

trap "jobs -p | xargs kill ; trap - INT" INT ; cmd1 & cmd2 & cmd3 &
# replace `cmds` with your command

그것이 하는 일은 모든 백그라운드 작업을 종료하고 기본 동작으로 되돌리기 위해 Ctrl+를 잡는 것입니다.C

그런 다음 백그라운드에서 모든 명령을 실행합니다.

Ctrl+ 를 클릭하면 C모든 트랩이 종료되고 트랩이 기본 동작으로 재설정됩니다.

관련 정보