서브셸에서 `sleep`을 종료합니다.

서브셸에서 `sleep`을 종료합니다.

killBash에서는 수면 프로세스가 호출되는 것을 관찰했습니다.에 익숙해 서브셸에서 시작하면 종료됩니다. 이유를 이해하도록 도와주실 수 있나요?

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를 제공 할 것이라고 확신합니다 .)whilesleep

예를 들어 다음 스크립트를 고려해보세요.

foo() {
    sleep 5 &
    echo foo
}
tmp=$(foo)
echo end.

실행하는데 5초가 걸립니다.

그러나 해당 줄을 sleep로 변경하면 더 이상 명령 대체에 연결되지 않기 sleep 5 > /dev/null &때문에 스크립트가 즉시 반환됩니다 . sleep백그라운드 절전 모드는 시간이 초과될 때까지 백그라운드에서 계속 실행됩니다. 당신은 그것을 알아 차릴 가능성이 적습니다.

이는 특정 항목에 해당됩니다.명령 대체, 서브쉘 환경만이 아닙니다. ( (foo)하위 쉘일 수도 있지만 , { foo; }또는 foo여기에서만 작동해야 합니다.)

관련 정보