2016-10-04 3 views
2

출력을 파일로 리디렉션하고 KSH의 스크립트 반환 코드 (pipestatus 또는 pipefail을 사용할 수 없음)를 확인할 수 있어야합니다. 해결책을 찾았지만 확실하지 않습니다. 파일 디스크립터 4의 중요성은 누군가 설명해 주시겠습니까?출력 파일 설명자 리디렉션

{ 
rc=$(
{ 
    { 
    . somescript.sh 2>&1 
    echo "$?" >&3 
    } | tee -a somefile.txt 
} 3>&1 >&4 4>&- 
) 
} 4>&1 

echo "${rc}" 

답변

2

rc=$(...)는 리턴 코드가 (...) 내에서 코드 파일 기술자 (FD) 1에 인쇄되어 어떤된다는 것을 의미합니다. 그래서, 어떻게 든 somescript.sh 출력은 fd 1에서 벗어나야하고 나중에 다시 가져와야합니다. echo 라인은 fd 3somescript.sh의 리턴 코드를 출력합니다. 그런 다음 3>&1은 저장된 반환 코드를 fd 1으로 보냅니다. 여기서 $(...)이이를 나타냅니다. 그러나 이것은 이전 fd 1 ({somescript 2>&1 } | tee에서)이 갈 곳이 없다는 것을 의미합니다. 따라서 이전 fd 1은 fd 4으로 >&4으로 리디렉션됩니다 (입력측은 사용되지 않으므로 4>&-으로 닫힙니다). 그런 다음 $(...)이 끝나면 4>&1somescript|tee의 출력을 다른 프로그램이 예상하는 fd 1에 다시 출력합니다.

휴! >&4없이

, somescript.sh의 출력과 echo "$?"의 출력이 때문에 3>&1의 FD 1에 혼합 될 것이다. 따라서 fd 4은 fd 1이 리턴 코드를 전달하는 데 사용되는 동안 somescript.sh의 실제 출력을 보관하는 펜입니다.

+0

필자는 항상 $ (...)가 stdout에서 읽는다고 생각했는데, 이는 fd 1이 일반적으로 가리키는 점이지만 fd 1에서 읽으면 많은 의미가 있습니다. 감사. – dood

+0

fd 1은 표준 출력을 가리 키지 않습니다; 그것은 * 표준 출력입니다. – chepner

+0

@chepner ah ok, 해명 해 주셔서 감사 드리며, 보통 stdout은 터미널을 가리 킵니다. – dood

1

명명 된 파이프를 사용하고자하는 경우에는 모든 파일 기술자 논쟁으로 분배 할 수 있습니다 : 그것은 명명 된 파이프로부터 입력을 읽으셔서, 여기

mkfifo p 
tee -a somefile.txt < p & 
. somescript.sh > p 
rc=$? 

, 우리는 백그라운드에서 tee을 실행 p. 작업이 시작되면 스크립트를 소스로 지정하고 출력을 명명 된 파이프로 리디렉션합니다. 스크립트가 완료되면 일반 할당 문을 사용하여 종료 상태를 rc으로 저장할 수 있습니다. 그러면 파이프의 셸 끝이 닫히고 다른 끝도 닫히고 tee을 종료 할 수 있습니다.

+0

처음에 터미널을 가리키는 fd'1'을 사용하여 이것을 실행하면'tee ... &'는'somescript.sh'가'p '를 출력하기 시작할 때'SIGTTOU'로'tee'를 멈추게 할 것입니까? – cxw

+0

이론 상으로는 그렇습니다.하지만'ksh'는'tee'가 터미널에 직접 쓸 수 있도록'SIGTTOU'에 대한 기본 동작을 무시해야합니다. (솔직하게 말해서, 내가 이것을 테스트했을 때 아무런 문제가 없다는 것을 알았 기 때문에'SIGTTOU '가 무엇인지를 찾아야 만했다.) – chepner

+0

[위의 코드에서 버그를 조심하며, 그것을 올바르게 증명했지만 시도하지 않았다. "] (http://staff.science.uva.nl/~peter/knuthnote.pdf) * Knuth * :) 감사합니다! – cxw