두 개의 하위 쉘이 stdout에 쓸 때 출력 정렬

두 개의 하위 쉘이 stdout에 쓸 때 출력 정렬

다음과 같은 형식의 명령이 있습니다.

input | tee >(subshell) | mainshell

서브쉘과 메인 쉘 모두 표준 출력에 기록합니다. 따라서 출력이 동기화되지 않습니다. 예를 들어

echo "Hello\nWorld" | tee >(grep -o ell | tr 'a-z' 'A-Z') | grep orld | sed 's/orl/ORL/g'

위 명령이 인쇄됩니다.

ELL
WORLd

가끔 그리고

WORLd
ELL

다른 시간.

임시 파일/이름이 지정된 fifo를 사용하지 않고도 예상 순서대로 되어 있는지 확인하는 쉬운 방법이 있습니까? 일부 파일 설명자 리디렉션을 켜면 도움이 될까요?

고쳐 쓰다:

순서는 메인 쉘의 출력, 그 다음 서브 쉘의 출력(또는 그 반대)을 의미합니다. 결정적이라면 필요에 따라 바꿀 수 있습니다.

이는 아래와 같이 fifo의 이름을 지정하여 달성할 수도 있습니다.

mkfifo f1 f2
echo "Hello\nWorld" | tee >(grep -o ell | tr 'a-z' 'A-Z' > f1) | grep orld | sed 's/orl/ORL/g' > f2 &
cat f1 f2
rm f1 f2

임시 FIFO나 파일을 피할 수 있는지 알고 싶습니다.

답변1

임시 파일/이름이 지정된 fifo를 사용하지 않고도 예상 순서대로 되어 있는지 확인하는 쉬운 방법이 있습니까? 일부 파일 설명자 리디렉션을 켜면 도움이 될까요?

설마. >(...)그리고...|...아니요경계 보존 - 단일 쓰기가 다른 쪽 끝에서 다중 읽기로 바뀌지 않을 것이라는 보장은 없습니다(또는 그 반대).

특정 순서를 적용하려면 권고 잠금을 사용할 수 있습니다. 참조flock(1)그리고flock(2)맨페이지. 이를 달성하는 방법은 주로 subshell프로그램 작동 mainshell방식 에 따라 달라집니다. 비협력 프로그램을 맹목적으로 잠그면 쉽게 교착 상태가 발생할 수 있습니다(작동하는 경우).

답변2

GNU Parallel은 순서를 변경하지 않고 강제로 유지할 --tee수 있습니다 .--keep-order

ell() {
  grep -o ell | tr 'a-z' 'A-Z'
}
orld() {
  grep orld | sed 's/orl/ORL/g'
}
export -f ell
export -f orld

echo "Hello\nWorld" | parallel -k --tee --pipe ::: ell orld

그러나 배후에서 fifo와 임시 파일을 사용합니다. 그러나 문제를 직접 처리하지 않는 것이 목표라면 이것이 해결책이 될 수 있습니다.

이 솔루션은 tmpfile을 사용하지만 거의 즉시 연결이 해제됩니다.

myfunc1() { grep -o ell | tr 'a-z' 'A-Z'; }
myfunc2() { grep orld | sed 's/orl/ORL/g'; }

touch tmp1 tmp2
(
    echo "Hello\nWorld" |
        tee >( (rm tmp1; myfunc1) > tmp1 ) |
        (rm tmp2; myfunc2) > tmp2
    cat <&3
    cat <&4
) 3< tmp1 4< tmp2

또는 더 짧게:

(
    rm tmp1 tmp2
    echo "Hello\nWorld" |
        tee >( grep -o ell | tr 'a-z' 'A-Z' >&5 ) |
        grep orld | sed 's/orl/ORL/g' >&6
    cat <&3
    cat <&4
) 5> tmp1 6> tmp2 3< tmp1 4< tmp2

관련 정보