問題很簡單:我發現有可能很有用開啟(和關閉)我需要的每個時刻某個正在運行的程式的輸出。更準確地說,我希望能夠自由地將它們的標準輸出(和錯誤)從當前 shell 重定向到另一個 shell、重定向/dev/null
到檔案或返回到原始 shell。
我尋找一些直接(且安全)的東西,利用我所知道的事實提早我將打開和關閉輸出。我也發表一個答案。
下面是我的第一次嘗試。假設我在 35 號外殼工作。
$ who am I # the command line to ask where am I
myuser pts/35 ... # The answer
我的嘗試從指向該終端的符號連結開始
ln -s /dev/pts/35 MyOutput # The command to link
這個想法是啟動程序並將重定向設置為該鏈接
./Execute_program > MyOutput
它有效,它將輸出重定向到我的終端,但是當我發出更改連結的命令時,
ln -sf /dev/null MyOutput
連結發生變化,但重定向不會改變我多麼希望。它不會因正在運行的進程而改變。如果我以相同的方式啟動一個新程序,重定向將遵循連結的新規定。
如果我再次開始並將輸出連結/dev/null
設為預期抑制,但當我再次更改連結時,重定向不會更改。
如果我做一個鏈接到一個鏈接,我會得到相同的結果。使用hard link
不會改變情況。
可悲的是shell 在啟動時擴展命令列。
是否有可能以類似的方式完成這項工作,或者我可以找到如何與連結已更改的進程(或 PPID 進程)進行通訊?
筆記:
這是「如何重定向正在運行的進程的輸出?」系列的一個問題,但它並不是從這一點開始的“Ops 我啟動了程序,但忘記重定向輸出。現在我想這樣做”,但從相反的角度來看:「我如何啟動一個程序,其明確的目標是在稍後階段將損失重定向到其他地方?」。
當不可能(或不方便)修改程式的原始程式碼時,我打算使用這樣的過程。
我讀可以disown
處理、使用screen
並從一個螢幕傳輸到另一個螢幕...或使用調試器來攔截進程...所有這些解決方案都可以透過大量的經驗和努力來發揮作用,但其中一些解決方案也呈現一定比例的風險。
答案1
我透過mkfifo
建立一個命名管道找到了一個解決方案,或者先進先出。
就像建立符號連結一樣簡單,並且可以使用 shell 允許的所有重定向。
mkfifo MyOutput
ls -l
給出
0 prw-r--r-- 1 My_username My_username 0 May 11 17:45 MyOut|
我可以透過重定向到該連結來啟動該程序
./Execute_program > MyOutput & cat MyOutput
並且輸出開始在終端上流動。
如果我按ctrl+c我會中斷流程,但不會中斷正在運行的進程(我必須使用類似kill pid
或 的東西kill %1
來執行此操作)。
當第二次我會問先進先出要在終端機上轉儲(再次使用cat MyOutput
),它將開始轉儲該時刻的輸出。
注意和警告:
- 直到我不會要求
FIFOs
它的轉儲將保存所有輸出。
正如我第一次問的那樣,它會沖走全部。 - 我可以重定向(或附加)到另一個文件
cat MyOutput >> NewRealFile
cat MyOutput
我也可以從另一個終端使用!- 警告:如果我要求 2 個不同的程式(或實例)將輸出重新導向到相同的
FIFOs
通量將被合併(沒有先驗區分該行來自哪個程式的方法)。 - 警告:如果我詢問兩次或多次(可能來自不同的終端),它將為每個請求提供一行,將輸出拆分給請求者。也許有一個安全的解決方法...
答案2
如果我正確理解你的問題:
script 1>>~/out.fifo 2>>~/error.fifo
然後要監視你可以執行以下操作:
watch cat ~/out.fifo
您可以使用真實文件而不是 Fifos
script 1>/tmp/$0-out 2>/tmp/$0-error
然後 tail -f 它們,當您再次運行腳本時它們將被替換。
我更喜歡第二種方法,或只使用多工器(即螢幕或本周流行的轉世)
screen -t "name" bash -c 'script'
然後
screen -r
「監視」並按 ctrl+ad 分離。
如果您想在運行後查看輸出,請確保在腳本末尾暫停。
答案3
如果我是你,我只是將輸出重定向到一個文件,然後當我想查看輸出時尾部該文件...如果你認為輸出會相當長,你可能想限制該文件的大小,或者如果您認為輸出會相當快,則將檔案寫入記憶體而不是磁碟上,但如何做這些事情是另一個問題。