빌드 도구는 표준 출력을 닫지 않는 데몬을 생성합니다. 이로 인해 셸 파이프라인이 중단되는 것을 어떻게 방지할 수 있나요?

빌드 도구는 표준 출력을 닫지 않는 데몬을 생성합니다. 이로 인해 셸 파이프라인이 중단되는 것을 어떻게 방지할 수 있나요?

(비공개 소스) 공급업체별 빌드 도구(FPGA 레이아웃 도구인 Microsemi Designer)를 사용하고 있습니다. 쉘 스크립트에서 호출합니다(매우 단순화됨).

...  # Setup

/opt/.../designer SCRIPT:my_script.tcl |tee build.log

...  # Postprocessing

문제는 designer프로세스가 종료된 후에도 tee프로세스가 계속 실행되어 스크립트가 계속 실행되지 않는다는 것입니다.

내가 이해하는 한, 이는 designer수명이 긴 데몬인 을 생성 windu_scmd50하고 해당 데몬이 (에서 상속받은 designer) 표준 출력을 닫지 않기 때문입니다. 따라서 tee결코 오지 않는 표준 입력(파이프에 연결됨)에서 EOF를 기다리고 있습니다.

이것이 문제의 원인이라는 증거:

  • pstee 프로세스는 계속 실행 중이지만 디자이너 프로세스는 실행되지 않음을 보여줍니다.
  • windu_scmd50프로세스를 종료하면 tee즉시 종료되고 스크립트가 계속됩니다(그러나 프로덕션에서는 이 작업을 수행할 수 없습니다).
  • designer의 출력을 to tee(또는 다른 것으로 파이프하지 않으면 in cat대신에 동일한 일이 발생함 tee) 스크립트가 중단되지 않습니다.
  • designer출력을 파일로 파이핑하지 않고 Jenkins에서 실행하면 Jenkins는 "프로세스 유출 파일 설명자"를 알려줍니다.이 도움말 페이지(분명히 Jenkins는 이 상황을 명시적으로 다루고 있습니다).

그래서:tee프로세스가 종료될 때(또는 그 직후에) 프로세스가 종료 되도록 하려면 어떻게 해야 합니까 designer?

내가 고려한 몇 가지 접근 방식은 다음과 같습니다.

  • 실행 중인 프로세스의 stdout을 리디렉션할 수 있나요?
  • 프로세스 종료를 감지하는 쉘 파이프 대신 사용할 수 있는 도구가 있습니까 designer?

가능하지 않은 일부 접근 방식은 다음과 같습니다.

  • 프로세스 의 출력을 무시할 수 없습니다 designer. 로그 파일에 기록해야 합니다.
  • windu_scmd50해당 프로세스는 컴퓨터의 다른 프로세스에서 사용될 수 있으므로 종료할 수 없습니다 .
  • 에 설명된 해결 방법젠킨스 도움말 페이지의 출력도 침묵시키기 때문에 적용되지 않는 것 같습니다 designer.
  • windu_scmd50 실행 파일을 래퍼로 대체하기 위해 도구 설치를 수정할 수 없습니다 .

추가 참고사항:

  • 프로세스 의 출력을 로깅 windu_scmd50하는 것이 좋지만 필수 사항은 아닙니다. 그러나 디자이너 프로세스의 출력을 기록해야 합니다.
  • 실제로 designer는 와 사이에 tee타임스탬프를 추가하는 또 다른 필터가 있습니다( designer ... |ts -s |tee build.log).
  • 특정 기능을 사용하는 bash것은 허용됩니다. 와의 호환성은 sh필수 사항이 아닙니다.

다음은 문제를 보여주는 최소한의 예입니다( test.sh).

#!/bin/bash
echo "Start"
sleep 10 &    # Background process that does not close stdout
echo "End"

이 스크립트를 직접 호출( ./test.sh)하면 "Start"와 "End"가 인쇄되고 즉시 완료됩니다. 출력을 다른 프로세스( ./test.sh |cat)로 파이프하면 "Start" 및 "End"가 즉시 인쇄되지만 완료되기 전에 10초 동안 일시 중지됩니다.

답변1

매우 간단한 해결 방법은 프로세스가 종료된 후 스트림에 메시지를 삽입하는 것입니다 designer. cat앞의 -like 필터는 메시지 tee를 발견할 때 종료되어야 합니다.

다음과 같습니다.


{ /opt/.../designer SCRIPT:my_script.tcl; echo message; } \
| sed -n '/^message$/q;p' | tee build.log

노트:

  • designer(또는 표준 출력을 상속하는 모든 것이) 메시지를 인쇄하면 조기 sed에 종료됩니다. 을 선택하세요 sTr1ng_Unlik3ly t0-Be enCOUnTered_in vvhat designer PRinT5. ASCII EOT 문자(8진수 004)를 선택하는 것이 좋습니다.
    { …; printf '\004\n'; } | sed -n "/^$(printf '\004')\$/q;p" | …

  • 처리할 수 있는 것에는 한계가 있습니다 sed. 보다이 답변은grep, 와 비슷합니다 sed.

  • ^message$만을 포함하는 전체 줄과 일치합니다 message. 이는 프로세스의 출력(있는 경우)이 designer개행 문자로 끝나는 것으로 가정합니다(즉, 마지막 줄이 완료되었습니다. 참조).불완전한 줄); 그래야만 message자체 라인에 있게 됩니다. designer확실하게 불완전한 라인을 생성 한다면 당신은 sed -n '/message$/{s/message$//;p;q};p'. 어느 쪽이든 가능하다면 원하는 것입니다 sed -n '/^message$/q;/message$/{s/message$//;p;q};p'. 불완전한 행은 designer완전한 행이 됩니다.

  • 침묵하지 않는 후손이 designer방해할 수 있음:

    • message전체 라인을 출력하려고 시도하더라도 중간 라인이 나타날 수 있습니다 . 우리에게는 마치 불완전한 줄이 생성된 sed것처럼 보일 것입니다 .designer
    • 선택한 메시지가 매우 길면 다른 데이터와 함께 인터리브된 파이프에 나타날 수 있습니다(참조이 답변그리고PIPE_BUF여기). 그러한 경우 우리는 sed그것을 전혀 감지하지 못할 것입니다.

관련 정보