kill
Bash에서는 수면 프로세스가 호출되는 것을 관찰했습니다.에 익숙해 서브셸에서 시작하면 종료됩니다. 이유를 이해하도록 도와주실 수 있나요?
function foo () {
# Start a loop with `sleep` in the background
while true; do
>&2 echo looping
sleep 5
done &
# Wait for user input, then kill the "sleep" loop
loop_id=$!
read -p 'press enter' DUMMY
kill $loop_id
}
echo $(foo) # Call foo within a subshell
echo "DONE"
마지막 줄이 서브쉘을 사용하는지 여부에 따라 두 가지 서로 다른 상황이 발생할 수 있습니다.
- 서브셸 호출을 사용하여 호출을
echo $(foo)
충족하기 위해 Enter 키를 누르면read
스크립트가sleep
끝까지 종료되지 않습니다. foo
함수를 호출하는 대신 just를 사용하면$(foo)
Enter 키를 누르자마자 스크립트가 종료됩니다.
이 장난감 예제가 있지만 실제 작업에서는 표준 출력을 foo
쉘 변수로 캡처하고 싶기 때문에 가능한 한 빨리 서브쉘을 종료하고 싶습니다. 두 가지 목표를 동시에 달성할 수 있는 방법이 있나요?
답변1
명령 대체를 사용하면 $(foo)
쉘은 명령 대체에 대한 모든 입력이 수신될 때까지 기다립니다. 실행 중인 sleep
파일 설명자(아마도 파이프)의 복사본은 쉘이 명령 대체 출력을 읽는 위치에 연결됩니다. (또한 내부 PID 가 아닌 $!
루프를 실행하는 쉘의 PID를 제공 할 것이라고 확신합니다 .)while
sleep
예를 들어 다음 스크립트를 고려해보세요.
foo() {
sleep 5 &
echo foo
}
tmp=$(foo)
echo end.
실행하는데 5초가 걸립니다.
그러나 해당 줄을 sleep
로 변경하면 더 이상 명령 대체에 연결되지 않기 sleep 5 > /dev/null &
때문에 스크립트가 즉시 반환됩니다 . sleep
백그라운드 절전 모드는 시간이 초과될 때까지 백그라운드에서 계속 실행됩니다. 당신은 그것을 알아 차릴 가능성이 적습니다.
이는 특정 항목에 해당됩니다.명령 대체, 서브쉘 환경만이 아닙니다. ( (foo)
하위 쉘일 수도 있지만 , { foo; }
또는 foo
여기에서만 작동해야 합니다.)