POSIX sh는 하위 프로세스에 대한 참조를 유지하기 위해 $!를 확장해야 합니까?

POSIX sh는 하위 프로세스에 대한 참조를 유지하기 위해 $!를 확장해야 합니까?

사양

~에 따르면온라인 POSIX 사양, 쉘 및 유틸리티, 쉘 명령 언어, 섹션 2.9.3 목록에서 비동기 목록에 대한 내용은 다음과 같습니다.

비동기 목록의 요소(<&>로 끝나는 목록 부분, 예:명령 1, 위) 셸에 의해 시작되면 비동기 목록 요소의 마지막 명령의 프로세스 ID가 현재 셸 실행 환경 내에서 알려져야 합니다. 셸 실행 환경을 참조하세요. 프로세스 ID는 다음 때까지 알려진 상태로 유지되어야 합니다.

  • 명령이 종료되고 애플리케이션은 프로세스 ID를 기다립니다.

  • $!현재 실행 환경에서 " "(이전 비동기 목록에 해당)이 확장되기 전에 또 다른 비동기 목록이 호출됩니다.

구현 시 현재 셸 실행 환경의 알려진 프로세스 ID 목록에서 최신 항목을 {CHILD_MAX}개 이상 유지할 필요가 없습니다.

기타 관련 인용문:

  • 위에서 섹션 2.12 셸 실행 환경:

    셸 실행 환경은 다음 부분으로 구성됩니다.

    […]

    • 이 셸 환경에 알려진 비동기 목록에 있는 마지막 명령의 프로세스 ID는 비동기 목록을 참조하세요.
  • Shell & Utilities, Utilities에서 잠시 기다려 주십시오.

    셸이 비동기 목록(비동기 목록 참조)을 시작할 때 비동기 목록의 각 요소에 있는 마지막 명령의 프로세스 ID는 현재 셸 실행 환경 내에서 알려져야 합니다. 셸 실행 환경을 참조하세요.

    […]

    대기 유틸리티가 피연산자 없이 호출되면 호출 셸에 알려진 모든 프로세스 ID가 종료되고 0 종료 상태로 종료될 때까지 기다립니다.

    […]

    알려진 프로세스 ID는 현재 셸 실행 환경의 대기 호출에만 적용됩니다.

어찌할 바를 모르는

Bash에서 help wait"현재 활성화된 모든 하위 프로세스"를 지정합니다.

사양에서는 알려진 모든 프로세스 ID만 지정하며 다른 비동기 목록을 호출하면 프로세스 ID가 "잊혀지는" 것으로 보입니다.

POSIX 사양을 올바르게 해석하면 다음 프로그램은 5초만 기다립니다.

#! /bin/sh
sleep 10 &
sleep 5 &
wait

$!이전에 등장한 적이 없어서 아이디를 잊어버리고 기다리지 않으셨나요 sleep 5 &?sleep 10

마찬가지로 두 줄 사이에 삽입하는 것도 : $!잊혀지지 않겠죠?

내 논리를 더 명확하게 설명하겠습니다.

  1. 사양: 알려진 프로세스. ID는 셸 실행 환경의 일부입니다. 구현 세부 사항은 중요하지 않기 때문에 이것이 일부 목록이라고 상상해 봅시다.
  2. SPEC: command &프로세스에서 결과를 실행합니다. 비동기 ID는 command"알려져 있습니다"(, 목록에 있음).
    • SPEC(의심스럽지만 첫 번째 인용 참조): command2 &어떤 방식으로든 확장하지 않고 실행하면 $!proc의 이전 명령 ID가 다음과 같이 됩니다.더 이상 알려지지 않음! (그러나 이제 proc.ID가 알려졌습니다 command2.)
  3. SPEC: wait매개변수 없이 알려진 절차만 사용합니다. 신분증.
  4. 결론: 따라서 비동기 명령 간에 확장을 강제하지 않으면 일부 하위 프로세스를 기다리는 것을 잊어 $!버릴 수 있습니다 .wait

어떤 사람들은 wait모든 과정을 기다린다고 생각합니다. 사양은 특정 정의가 있는 "알려진" 프로세스를 나타냅니다. 어떤 사람들은 사양에 그런 내용이 나와 있지 않더라도 "알려진"이 "$!"를 의미한다고 생각합니다(또한 "알려진 프로세스 ID"는 복수형이 아니라 $!).

나는 이것이 논쟁의 여지가 있다는 데 동의합니다. 내가 새 작업을 시작할 때 쉘은 내 작업을 잊지 않습니다. 그렇다면 사양을 어디서 잘못 읽었습니까?

질문

  • POSIX에서는 루프에서 비동기 목록을 시작할 때와 같이 인수 없이 동작을 합리적으로 만들기 $!위해 실제로 for를 사용해야 합니까 ?wait
  • 실제로 이런 방식으로 사양을 구현하는 쉘(POSIX 또는 기타)이 있습니까(: $! expand async. proc. ID to prevent forgetting it, 실제로 nullary를 사용하는 프로그램에 추가하는 것을 피할 수 있습니까 wait?

답변1

두 개의 백그라운드 작업을 시작할 때 $!먼저 첫 번째 작업의 PID로 설정한 다음 두 번째 작업의 PID로 설정합니다. 이는 쉘이 첫 번째 작업을 추적하지 못한다는 의미는 아닙니다. 쉘은 실제로 당신이 그것을 무엇을 위해 사용하는지 상관하지 않습니다 $!.

표준 텍스트에서 wait인수 없이 대기할 것이라고 말하는 방법에 유의하세요.모두백스테이지 작업? 이는 시작된 백그라운드 작업 수 및 $!이 매개변수로 수행하거나 수행하지 않는 작업과 관계가 없습니다.

표시된 예에서는 두 개의 절전 호출이 백그라운드에서 실행되고 있으며 두 호출이 모두 종료될 때까지 대기합니다. 즉 wait호출이 반환되는 데 10초가 걸립니다.

관련 정보