建置工具產生一個不會關閉其標準輸出的守護程式。如何防止這種情況導致我的 shell 管道停止運作?

建置工具產生一個不會關閉其標準輸出的守護程式。如何防止這種情況導致我的 shell 管道停止運作?

我正在使用(閉源)供應商特定的建造工具(Microsemi Designer,一種 FPGA 佈局工具)。我從 shell 腳本呼叫它(高度簡化):

...  # Setup

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

...  # Postprocessing

問題是:即使designer進程終止後,tee進程仍繼續執行,因此腳本不會繼續。

據我了解,這是因為designer生成了一個長期存在的守護進程 , windu_scmd50並且該守護程序不會關閉其標準輸出(它繼承自designer)。因此,tee正在等待其標準輸入(連接到管道)上的 EOF,但它永遠不會到來。

有證據表明這是問題的原因:

  • ps顯示 tee 進程仍在運行,但設計器進程未運行。
  • 當我終止windu_scmd50進程時,tee立即終止並且腳本繼續(但我無法在生產中執行此操作)。
  • 如果我不透過管道將designerto的輸出tee(或其他任何東西;cat代替 of發生同樣的事情tee),腳本不會停止。
  • 如果我designer從 Jenkins 運行(不將輸出通過管道傳輸到檔案),Jenkins 會通知我“進程洩漏的檔案描述符”,連結到 這個幫助頁面(顯然,詹金斯明確處理了這種情況)。

所以:如何確保tee進程在進程終止時(或之後不久)終止designer

我考慮過的一些方法:

  • 是否可以重定向正在運行的進程的標準輸出?
  • 是否有一個工具可以取代 shell 管道來偵測進程的終止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

一個非常簡單的解決方法是在進程終止後向流注入一條訊息designercat前面的類似過濾器應該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 字元(八進位 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根本不會檢測到它。

相關內容