Terminal

如何防止子程序干擾bash提示?

  • April 7, 2022

有問題的應用程序是 DaVinci Resolve。我從終端啟動它。當我關閉它時,來自應用程序的消息“Socket Disconnected”被寫入終端輸出。然後 bash 提示符正常顯示。我開始輸入新命令,突然在終端“Socket Disconnected”中出現另一條消息。這會干擾我所做的輸入。它看起來像這樣:

[andrew@unihost ~]$ davinci-resolve
... # Now I exit the application.
Host 'Fusion' Removed
FusionScript Server [37457] Terminated
Socket disconnected
[andrew@unihost ~]$ ls ls Socket disconnected
wtf!!!^C
[andrew@unihost ~]$

影片展示:https ://youtu.be/arcCOjrN7kw

為什麼會發生這種情況,有沒有辦法防止這種情況發生?

我的猜測是主程序有一個子程序,即使在主程序死後它仍然活著。我找到了這個答案。是開發商的錯嗎?我可以以某種方式解決這個問題(對於子程序可能是 nohup)?

初步說明

我根本沒有測試davinci-resolve過。這個答案被設計為通用的。


分析

davinci-resolve您的 shell在將自身放回前台並列印提示之前等待退出。davinci-resolve顯然,在主程序退出並且外殼做出反應後,主程序的某些子程序(或進一步的後代)會列印出不需要的消息。


解決方案

解決方案可能很簡單:

davinci-resolve | cat

訣竅是cat在所有寫入管道的程序都關閉它們的管道末端之前不會退出。麻煩的孩子可能從 main 繼承了 stdout davinci-resolve,所以cat會等待它。通常,即使不需要的消息被列印到 stderr 或/dev/tty(即它繞過我們的cat),這也會起作用。重要的是孩子保持管道打開,即使它正在列印到其他地方。

有以下缺點:

  • 整個管道的退出狀態將來自於cat,而不是來自於davinci-resolve在某些 shell 中,您可以對它做一些事情
  • 來自(及其後代)的 stdout 和 stderrdavinci-resolve將失去同步,因為前者通過cat而後者不通過。
  • 如果你Ctrl+c那麼你將殺死cat,可能在其他程序完成列印之前,所以你可能會錯過一些你確實想看到的輸出。此外,如果麻煩的消息被列印到 stderr,那麼無論如何它都會被列印出來,可能是在你看到提示之後。

但是,您可以對+cat免疫:Ctrl``c

davinci-resolve | sh -c 'trap "" INT; exec cat'
  • 麻煩的過程可能會提前關閉或重定向其標準輸出,但仍會列印到標準錯誤。在這種情況下cat不會等待它。
  • 麻煩的程序可能被設計為保留,不需要的消息並不意味著程序退出。如果這個過程仍然存在並保持管道打開,那麼我們的cat意志就會存在;你顯然不想要這個。似乎不太可能有任何davinci-resolve遺骸的後代(除非有錯誤),但總的來說它可能會發生。

由於其中一些原因,您可能希望通過 stdoutstderr傳遞cat. 免疫+仍然是一個好主意catCtrl``c

 davinci-resolve 2>&1 | sh -c 'trap "" INT; exec cat'

現在請注意,您無法將 stderr davinci-resolve(及其後代)與 stdout 區分開來,它們都經過 viacat及其 stdout。這應該不是問題,因為無論如何您都希望它們在終端中混合。如果您想單獨重定向或擷取它們,那麼您應該放棄我們的裝置並從頭開始。

可能是麻煩的程序提前關閉或重定向其 stdout 和 stderr,並將不需要的消息直接列印到/dev/tty範例)。在這種情況下,我們cat無能為力。


外殼函式

您可以將我們的解決方案實現為 shell 函式:

davinci-resolve() {
  command davinci-resolve "$@" 2>&1 | sh -c 'trap "" INT; exec cat'
}

該函式支持將參數傳遞給davinci-resolve,但其退出狀態來自cat,而不是來自davinci-resolve程序(如果有問題,請參閱已經給出的連結以獲取想法)。

引用自:https://unix.stackexchange.com/questions/698112