在所有可見的 shell 上執行命令
我目前正在執行一個平鋪視窗管理器,我希望能夠使用一個自定義功能,該功能與我使用 tmux 時的功能相同,它允許我在目前視窗的所有可見 shell 中執行命令(EG
ta cd to/dir
)該命令/功能被稱為
ta
“對所有人”我設法創建了以下功能:
function ta() { local current_workspace="$(xdotool get_desktop)" local to_execute="`if [[ \"$current_workspace\" = \"\$(xdotool get_desktop)\" ]]; then; $@; fi`" for pts in $(ls /dev/pts | grep -o '[0-9]*'); do echo "$to_execut" > /dev/pts/$pts done }
如果我像這樣手動執行命令:
te="`if [[ \"$current_workspace\" = \"\$(xdotool get_desktop)\" ]]; then; xdotool get_desktop; fi`" echo "$te" > /dev/pts/1
0
我在目前的 shell 中看到了輸出如果我嘗試執行我的
ta
,我什麼也得不到,而且我注意到即使對於有效的命令,也只是輸出某些東西的命令,所以我實際上是在執行我正在儲存的字元串然後輸出它。有沒有人有更好的建議?
為什麼您嘗試的方法不起作用
終端是終端提供者和終端中執行的應用程序之間的雙向通信通道。終端設備代表應用程序的一方:向終端設備寫入是請求終端提供者顯示您所寫的內容,從終端設備讀取是對終端提供者發送使用者輸入的請求。因此,當您執行時
echo "$to_execut" > /dev/pts/$pts
,這只是一些在終端上顯示某些內容的隨機程序。終端的提供商端通常不作為設備公開。該部分的工作方式取決於系統以及它是物理終端還是終端仿真器。在 Linux 上,終端仿真器會打開設備
/dev/ptmx
。因為這個設備是多路復用的,所以你不能只是打開它並獲得終端仿真器所具有的等效句柄。在沒有終端仿真器程序合作的情況下假裝是終端仿真器的唯一方法是將調試器附加到程序。無論如何,將輸入註入終端是一個壞主意。如果終端中正在執行程序怎麼辦?如果在 shell 提示符下有一個部分鍵入的命令怎麼辦?
如何在多個視窗中輸入
您可以使用 xdotool 在終端模擬器的視窗中模擬按鍵。它既麻煩又危險(如果 shell 沒有在空提示符處等待,這可以做任何事情)——就像您最初嘗試做的那樣。
這僅適用於在 GUI 視窗中執行的 shell。如果您在終端模擬器中使用選項卡,則只有前台選項卡會接收輸入。如果您使用諸如 screen 或 tmux 之類的多路復用器,則只有目前顯示在 GUI 視窗中的視窗(如果有)將接收輸入。
使用信號
向外殼發送信號。這是讓程序做出反應的正常方式。這有局限性:只有幾個不同的信號,並且您不能將任何資訊附加到信號上,因此接收者必須執行一些預定義的操作。從好的方面來說,程序可以準確地選擇何時做出反應,特別是對於 shell,它們會等到“安全”時間(而不是在執行前台命令時)。
要使 shell 對信號做出反應,請使用
trap
內置命令。潛在信號只有幾種選擇:
- SIGUSR1和SIGUSR2沒有傳統意義。預設情況下,它們會終止該程序,因此如果您不能確定您只是將信號發送給 .
- 當視窗大小發生變化時,終端仿真器會發送SIGWINCH 。預設情況下它什麼都不做。Shell 處理它以更新
LINES
andCOLUMNS
變數,但除此之外,您還可以設置自己的陷阱以執行。SIGWINCH 的一個限制是,如果 zsh 目前正在執行前台作業,則陷阱根本不會執行。所以你可以做的是安排一個位置,比如說
~/.zsh_USR1
,從那個文件中讀取 zsh 的實例。USR1_COMMAND_FILE=$HOME/.zsh_USR1 trap '[[ -r $USR1_COMMAND_FILE ]] && . $USR1_COMMAND_FILE' USR1
請記住,向所有 zsh 程序發送 SIGUSR1 將殺死任何尚未設置此陷阱的腳本!因此,只有在您確定了哪些 zsh 程序正在您要定位的視窗中執行時才發送它。