
여러 프로그램을 실행하는 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를 상속받습니다. 하지만 작업 제어가 없으면 위의 방법도 작동하지 않습니다.
차이점은 bash의 PID를 사용하는 트랩에 대한 이 kill 명령입니다. 이는 새 프로세스의 PGID가 되기 때문입니다.
trap 'kill -- -$$' EXIT
보다이 관련 Q또는여기서 Johannes 'fish' 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모두 죽고 트랩이 기본 동작으로 재설정됩니다.