반 비동기식 파이프


11

다음 파이프가 있다고 가정하십시오.

a | b | c | d

어떻게 완료 기다릴 수 c(나 b)에서 shbash? 즉, 스크립트 d는 언제든지 시작할 수 있으며 (대기 할 필요 는 없지만 ) c제대로 작동 하려면 전체 출력이 필요 합니다.

유스 케이스 는 이미지를 비교 하기 difftool위한 것 git입니다. 호출되어 git입력 ( a | b | c부분) 을 처리하고 비교 결과 ( 부분)를 표시해야합니다 d. 발신자는 a및에 필요한 입력을 삭제합니다 b. 즉, 스크립트에서 돌아 오기 전에 프로세스 c(또는 b)를 종료해야합니다. 반면에, 나는 d사용자 입력을 기다리고 있음을 의미 하기 때문에 기다릴 수 없습니다 .

c임시 파일에 결과를 쓰거나에서 FIFO를 사용할 수 있음을 알고 있습니다 bash. (FIFO가 도움이 될지 확실하지 않습니다.) 임시 파일없이이 작업을 수행 할 수 sh있습니까?

편집하다

아마도 c(또는 b) 프로세스 의 프로세스 ID를 신뢰할 수있는 방식으로 찾을 수 있다면 충분할 것 입니다. 그런 다음 전체 파이프를 비동기식으로 시작할 수 있으며 프로세스 ID를 기다릴 수 있습니다. 라인을 따라 뭔가

wait $(a | b | { c & [print PID of c] ; } | d)

수정 ^ 2

해결책을 찾았으며 의견 (또는 여전히 더 나은 해결책)을 환영합니다.


당신 은 완료 후에 만의 출력 d처리를 시작 하고 싶다는 뜻 입니까? 각 출력 라인 처리를 시작 하고 싶지 않습니까? ccd
terdon

@terdon : 아니요. d마음에들 때마다 언제든지 시작할 수 있지만 계속 진행 c하려면 먼저 완료해야합니다.
krlmlr

그것은 자기 모순적인 것처럼 보입니다. 필요할 d때 시작할 수 있다면 정확히 무엇을 기다리고 있습니까?
terdon

@terdon : 사용 사례를 보여주기 위해 확장되었습니다.
krlmlr

경우 d의 출력을 사용하지 않는 c메이크업의 어떤 이해하고 싶지 않아 보인다 d파이프 라인의 일부를. 그러나 d입력을 사용하는 경우 d접근 방식이 차이를 만들기 위해 입력을 모두 읽은 후에 입력에 대해 잠시 작업해야합니다.
Hauke ​​Laging

답변:


6
a | b | { c; [notify];} | d

예를 들어 환경 변수 ( kill -USR1 $EXTPID) 로 전달 된 PID에 대한 신호 또는 파일 ( touch /path/to/file) 을 생성하여 알림을 수행 할 수 있습니다 .

또 다른 아이디어 :

파이프 라인에서 다음 프로세스 (기다릴 수있는 프로세스)를 실행합니다.

a | b | { c; exec >&-; nextprocess;} | d

또는

a | b | { c; exec >&-; nextprocess &} | d

감사. 그러나 중간 출력을 위해 임시 파일을 작성하는 것이 더 장황하고 구문 분석하기 쉽습니다 (사람의 경우). 또한 신호와의 경쟁 조건을 피하려면 어떻게해야합니까? ... 나는 더 깨끗한 해결책을 원했지만 이것이 방법이라면, 그렇게하십시오.
krlmlr

@krlmlr 어떤 경쟁 조건이 있습니까?
Hauke ​​Laging

notify신호 트랩을 설정하기 전에 실행될 수 있습니다. 그 신호를 놓치지 않으려면 어떻게해야합니까?
krlmlr

@krlmlr 파이프 라인을 호출 한 스크립트는 자신 trap이 정의 된 후에 전송되는 신호 자체를받을 때까지 중지합니다 .
Hauke ​​Laging

편집 : 파이프가 루프에서 호출되어 제어 할 수 없습니다. 불행히도, { c; bg; }또는 { c; exit 0; }작동하지 않는 것 같습니다.
krlmlr

5

귀하의 질문을 올바르게 이해하면 다음과 같이 작동합니다.

a | b | c | { (exec <&3 3<&-; d) &} 3<&0

fd 3 트릭은 (대부분의) 일부 쉘이 stdin을 / dev / null로 리디렉션하기 때문 &입니다.



3

이것은 Hauke의 입력을 통해 시행 착오에서 찾은 것입니다.

a | b | { c; kill -PIPE $$; } | d

동등하게 :

a | b | ( c; kill -PIPE $$; ) | d

(후자는 {}파이프 내부의 경우 어쨌든 서브 쉘에서 실행 되기 때문에보다 명확 합니다.)

(비롯한 몇몇 다른 신호 QUIT, TERMUSR1작업)도 있지만,이 경우에는 신호의 설명은 단말기에 표시된다.

이것이 PIPE신호 의 원래 의도인지 궁금합니다 . 매뉴얼 에 따르면 :

SIGPIPE: PIPE프로세스가 다른 쪽 끝에 연결되지 않고 파이프에 쓰려고 할 때 신호가 프로세스로 전송됩니다.

즉, 인위적으로 파이프 신호를 서브 쉘에 보내면 자동으로 종료되어 최종 소비자 ( d) 만 남게됩니다.

이것은 모두에서 작동 sh하고 bash.


0

sponge"moreutils"패키지에서 프로그램을 사용할 수 있습니다 .

a | b | c | sponge | d

스폰지는 c배관하기 전에 출력 이 끝날 것입니다 d. 그것이 당신이 원하는 희망입니다.


0

당신은 할 수 있습니다 :

a | b | c | (d ; cat > /dev/null)

따라서 d완료되면는 끝날 때까지 cat나머지 c출력을 흡수합니다 .

확인. 의견 후, 대답은 d백그라운드에서 직접 시작 하는 것입니다.

하다:

a | b | c | (d &)

stdin 에서 읽는 데 문제가있는 경우 Stephane Chazelas 의 솔루션을 사용하십시오 .d


유스 케이스가 다른 방식으로 c끝나는 것이 두렵습니다. 보다 일찍 완료 d되며 완료 될 때까지 기다려야 c하지만 걱정하지 마십시오 d.
krlmlr

죄송합니다. 이해가되지 않습니다. 작업을 c마치고 d여전히 실행 중일 때 무엇을 하시겠습니까 ? 죽여 d?
angus

dGUI가 있으며 사용자가 닫을 때까지 실행할 수 있습니다.
krlmlr

알았어 ..하지만 벌써 일어난 일이야 때 a, b그리고 c자신의 작업을 완료, 그들은 가까운 표준 출력하고 종료; 만 d실행 상태로 유지됩니다. 완료 d되면 백그라운드 로 보내 c시겠습니까? 그게 다야?
angus

예, 완료 d되면 배경으로 보내야합니다 c.
krlmlr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.