Gnu Screen:在附加時執行指令

Gnu Screen:在附加時執行指令

有沒有辦法讓 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_COMMANDprecmd~/var/run/screen-12345.foo.env-update.shfoo

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重新連接到與前一個視窗大小不同的終端時,screenSIGWINCH訊號發送到 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。

相關內容