有沒有辦法讓 GNU Screen 在附加時進行偵測,並在附加時執行我擁有的 shell 腳本?這樣做的原因是我希望保持 X11 轉發的顯示變數正確,但我需要檢測螢幕何時重新連接到另一台電腦以觸發我的腳本。
謝謝。
答案1
您可以在附加之前運行screen -S foo -X setenv DISPLAY "$DISPLAY"; screen -S foo -rd
以更改進程的環境。screen
這不會影響現有的視窗。
您也許可以將 shell 配置為在每次顯示提示時檢查更新DISPLAY
(以及任何其他相關變量,例如)。 (這意味著,如果附加會話時 shell 處於提示符號處,XAUTHORITY
您可能必須按一次。)Bash在顯示每個提示符號之前進行評估。 Zsh在顯示每個提示之前運行函數。例如,如果您已將所需的環境分配放入腳本中(其中 12345 是螢幕進程的 pid,並且是會話名稱),則可以使用類似的內容(對於 zsh,未經測試;我不認為您沒有在bash 中分叉就可以逃脫):Enter$PROMPT_COMMAND
precmd
~/var/run/screen-12345.foo.env-update.sh
foo
precmd () {
local now=$SECONDS
set ~/var/run/"screen-$STY.env-update.sh"(Nms-$(($now-$screen_env_time)))
if [[ $# -ne 0 ]]; then
screen_env_time=$now
. ~/var/run/"screen-$STY.env-update.sh"
fi
}
在某些作業系統上,您可以從$PROMPT_COMMAND
或做的另一件事是讀取父進程的環境(這假設您已經更新了螢幕進程的環境)。precmd
例如,在 Linux 上使用 zsh(僅在螢幕下運行時才執行此操作):
precmd () {
local record
while read -r -d $'\0' record /proc/$PPID/environ; do
case ${record%%=*} in
DISPLAY|XAUHORITY) export $record;;
esac
done
}
從技術上講,您可以使用偵錯器變更另一個進程的環境。但它很有可能使該進程崩潰,因為程式的內部資料結構與核心保存的資料不符。
請注意,如果您在螢幕視窗內運行 ssh,這些解決方案都不會起到任何作用。
答案2
你最終想要的卻無法實現。即使您設法讓螢幕在連接時運行腳本,它仍然無法更改子進程的環境。
答案3
我認為 Giles 的解決方案是最通用的解決方案,但它有兩個缺點:(1) 直到運行命令後、重新附加後它才起作用,(2) 該命令在每次新連接時執行命令提示符。 (我能說什麼,我討厭浪費 CPU 週期)。還有一種替代方案,但它也不完美:當screen
重新連接到與前一個視窗大小不同的終端時,screen
將SIGWINCH
訊號發送到 shell,您可以捕獲該訊號:
trap some_function SIGWINCH
我編寫了一個 shell 腳本(與 .bashrc 一起取得),它利用這一事實來處理重新連接分離終端時重寫 SSH_AUTH_SOCK 和相關變數。在這裡查看該項目:https://gitlab.com/otheus.uibk/bashrc-ssh-agent。該腳本可以輕鬆修改,以便與 PROMPT_COMMAND 整合。
也許我們可以更新screen
一個選項,在重新連線時強制 SIGWINCH?我目前使用的是 4.1.0(隨 RedHat 7 一起提供),但目前版本是 4.6。