當我啟動 shell 時如何確定程式是否正在運行,如果程式尚未運行則啟動該程式?

當我啟動 shell 時如何確定程式是否正在運行,如果程式尚未運行則啟動該程式?

當我啟動 shell 時,在我的例子中是 bash 和/或 zsh,我需要向 .zshrc 和/或 .bashrc 添加哪些行來檢查程式是否已經在運行,以及程式是否尚未運行,啟動它?

範例:我正在啟動一個新的 zsh shell。如果 top 尚未運行,我想啟動 top 並讓它接管 shell。如果 top 已經在另一個視窗中運行,我希望 .zshrc 繼續加載並給我一個打開的終端。

6-16更新:

if ! pgrep -U $USER top >/dev/null; then
exec top
fi

上面的腳本滿足了我的要求。 -q 標誌對我不起作用,因為 -q 不是我的系統上的選項。所以我必須將 PID 透過管道傳輸到 /dev/null。謝謝 mveroone、Kusalananda 和 Thomas Dickey。

我有一些功能蔓延超出了原始問題的範圍。假設我在單一使用者係統上,無需輸入密碼即可成為 root 使用者。如果需要的話,我如何以root身分自動運行top?

6-18 好的,以 root 身分傳遞指令的功能蔓延問題已解決。我用它來啟動幾個

感謝您所有深思熟慮的回覆。

答案1

pgrep像這樣使用:

if ! pgrep -u $USER top >/dev/null 2>&1; then
    exec top
fi

解釋:

  • pgrep如果發現該命令正在運行,則實用程式將以零退出代碼退出。因此,否定該測試。
  • 也可以使用 來將其限制為當前用戶-u $USER,這樣它就不會因為某種原因而獲取其他人的進程。$USER是一個標準的 shell 變數。如果由於某種原因未定義,請嘗試使用$LOGNAME,如果失敗,請使用$( id -n -u )(但此時您必須問自己發生了什麼事,因為$LOGNAME標準 shell 變數)。
  • 我們不需要 的輸出pgrep,因此將標準輸出和錯誤流重定向到/dev/null

如果top(或其他)未發現正在運行,則exec根據OP的問題,它會替換外殼。

這應該適用於所有sh相容的 shell。

編輯:pgrepBSD 系統(OS X,OpenBSD,...)上的實作有一個-q選項可以讓它丟棄任何輸出,但pgrepLinux 上顯然沒有這個標誌。在 BSD 系統上,使用這個而不是稍微難看的重定向到/dev/null.

答案2

如果程式始終從 shell 啟動並且您可以完全控制它(即它沒有在第 3 方程式中硬編碼),那麼您可以使用某種鎖定機制,例如lockfileflock。例如透過新增

flock -n /tmp/top -c top

.bashrc/.zshrc您將確保只有 shell 的第一個實例將運行該top命令(除非您殺死它,然後將啟動另一個實例)。

您可能想要建立一個函數,以便能夠手動啟動命令(而不僅僅是在 shell 初始化時):

mytop () { flock -n /tmp/$0 -c top; }

mytop只要你想跑就跑。

答案3

同意這pgrep是要走的路,但也存在一些陷阱。您不需要使用該-q選項,因為您可以重定向輸出pgrep來消除該問題:

pgrep -U $USER top >/dev/null || exec top

陷阱在於它不是標準實用程序,因此您必須記住它可能不可移植。以下是一些幫助頁面連結:

環境USER變數更加完善,但似乎不在 POSIX 的 shell 清單中(請參閱2.5.3 Shell 變數)。相反,它指出這USER是已知正在使用的許多變數之一(請參閱註釋8.1 環境變數定義)。

這運行top你自己, 當然。如果您選擇讓它運行為,然後您可以將 變更$USER為然後使用(首選)或root運行。 POSIX 中都不存在(topsudosu查看列表)。後者 ( su) 在類 Unix 系統上隨處可用,但sudo通常是首選。所以你會有

pgrep -U root top >/dev/null || exec sudo top

除非您已設定sudo為不需要密碼,否則 shell 啟動時將提示您輸入密碼top

答案4

我會在我的 .zshrc (或其他)中附加這樣的片段:

if pgrep -u $USER 程式名
然後
    執行程式名

警告 :我還沒有測試過這段程式碼。請不要在 root 或伺服器上唯一的使用者上使用它。確保失敗時可以恢復。

相關內容