여러 동시 공동 프로세스를 가질 수 있습니까?

여러 동시 공동 프로세스를 가질 수 있습니까?

이것의도아래 테스트 스크립트 1 의 목적 은 "외부" 공동 프로세스(실행 중)를 시작하고 seq 3, 루프에서 이 공동 프로세스의 데이터를 읽고 while, 읽은 각 줄에 대해 외부 루프의 현재 반복을 식별하는 줄을 인쇄하고, "내부" 공동 프로세스를 시작하는 것입니다. " " 코프로세스( seq새 매개변수를 사용하여 실행 중)는 중첩된 while 루프에서 이 내부 코프로세스를 읽은 다음 이 내부 코프로세스를 정리합니다. 중첩된 while 루프는 내부 ​​코프로세스에서 읽는 각 줄에 대한 일부 출력을 인쇄합니다.

#!/bin/bash
# filename: coproctest.sh
PATH=/bin:/usr/bin

coproc OUTER { seq 3; }
SAVED_OUTER_PID="${OUTER_PID}"

exec {OUTER_READER}<&"${OUTER[0]}"
while IFS= read -r -u "${OUTER_READER}" OUTER_INDEX; do

    printf -- '%d\n' "${OUTER_INDEX}"

    START=$(( OUTER_INDEX * 1000000 ))
    FINISH=$(( START + OUTER_INDEX ))

    # (
      coproc INNER { seq "${START}" "${FINISH}"; }
      SAVED_INNER_PID="${INNER_PID}"
      exec {INNER_READER}<&"{INNER[0]}"

      while IFS= read -r -u "${INNER_READER}" INNER_INDEX; do
          printf -- '    %d\n' "${INNER_INDEX}"
      done

      exec {INNER_READER}<&-

      wait "${SAVED_INNER_PID}"
    # )

done
exec {OUTER_READER}<&-
wait "${SAVED_OUTER_PID}"

이 스크립트를 실행하면 다음과 같은 결과가 나옵니다.

% ./coproctest.sh
1
./coproctest.sh: line 30: warning: execute_coproc: coproc [12523:OUTER] still exists
./coproctest.sh: line 19: INNER_READER: ambiguous redirect
./coproctest.sh: line 21: read: : invalid file descriptor specification
./coproctest.sh: line 25: INNER_READER: ambiguous redirect
2
./coproctest.sh: line 19: INNER_READER: ambiguous redirect
./coproctest.sh: line 21: read: : invalid file descriptor specification
./coproctest.sh: line 25: INNER_READER: ambiguous redirect
3
./coproctest.sh: line 19: INNER_READER: ambiguous redirect
./coproctest.sh: line 21: read: : invalid file descriptor specification
./coproctest.sh: line 25: INNER_READER: ambiguous redirect

두 주석 줄의 주석을 모두 제거하면 거의 동일한 결과가 나타납니다.


질문 1:여러 개의 공동 프로세스를 동시에 실행할 수 있습니까?

질문 2:그렇다면 원하는 출력을 얻으려면 위 스크립트를 어떻게 수정해야 합니까?


1 코프로세싱을 시작한지 ​​얼마 안됐는데 아직 이해가 안되는 부분이 많습니다. 따라서 스크립트에는 부정확하거나 서투르거나 불필요한 코드가 포함되어 있는 것이 거의 확실합니다. 귀하의 답변에 자유롭게 의견을 제시하거나 이러한 약점을 수정해 주시기 바랍니다.

답변1

매뉴얼 마지막 부분의 "BUGS" 섹션에서 bash:

한 번에 하나의 활성 공동 프로세스만 있을 수 있습니다.

답변2

Q1: 동시에 여러 개의 공동 프로세스를 실행할 수 있습니까?

Bash v4 이상(현재 v5 포함)에는 @Kusalananda가 지적했듯이 공식적인 것이 없습니다.

하지만, 그건 말씀드릴 수 있어요가능한경고에도 불구하고 작업은 확실히 보장되지 않으며 YMMV입니다.이봐더 많은 통찰력을 얻으려면.

Q2: 그렇다면 예상한 출력을 얻으려면 위 스크립트를 어떻게 수정해야 합니까?

그것가능한(위에서 언급한 바와 같이) 다음 문제가 해결되면 제대로 작동합니다.

exec {INNER_READER}<&"{INNER[0]}"  # <-- lacks the '$' sign for the 'INNER[0]' variable

그 결과는 다음과 같습니다.

./coproctest.sh: line 19: INNER_READER: ambiguous redirect

메시지도 마찬가지입니다.

./coproctest.sh: line 21: read: : invalid file descriptor specification

정보.

문제를 해결하고 경고를 버리면 나에게 도움이 되었습니다.

다른 참고 사항은 다음과 같습니다.

  • coproc하위 프로세스(서브쉘, 명령 또는 스크립트)에 전달하려는 경우가 아니면 의 파일 설명자를 반복할 필요가 없습니다.
  • seq명령이 자연스럽게 빨리 완료되어 자동 변수가 사용되기 전에 사라지기 때문에 이렇게 하는 것입니다 . 여러분이 했던 방식으로 수행하면 이러한 중복 파일 설명자는 모든 후속 명령과 백그라운드 프로세스에 의해 상속됩니다. 이는 보조 프로세스가 실제로 입력 파이프를 사용하고 종료하기 전에 닫힐 때까지 기다리는 경우 바람직하지 않을 수 있습니다. 따라서 이 문제를 해결하는 또 다른 방법은 동기화 메커니즘을 사용하는 것입니다. 예를 들어 OUTER보조 프로세스를 만든 { seq 3; exec >&-; read; }다음 기본 스크립트의 입력을 사용한 다음 echo >&${OUTER[1]}; wait "${OUTER_PID}"보조 프로세스를 read계속하도록 두는 것입니다 wait. 변수가 사라지기 wait전에 실행이 발생한다는 보장은 없습니다 $OUTER_PID. 이 경우 경고 메시지를 음소거하거나 완전히 무시하고 다음을 사용할 수 있습니다.|| true
  • 개인적인 참고 사항으로, 동시에 여러 공동 프로세스를 수행하기로 결정한 경우 다음을 다시 구현할 수 있다는 점을 알려드립니다.거친coproc백그라운드 프로세스에서 Bash v3 구문과 명명된 FIFO를 사용 하고 mkfifoLinux에서 mkfifos 트릭 대신 프로세스 대체를 사용하는 것과 동일합니다 . Bash v4 구문을 사용하면 덜 복잡할 수 있지만 여전히 어려운 작업입니다.

관련 정보