GNU Screen が接続されたときにそれを検出し、接続されるたびにシェル スクリプトを実行する方法はありますか? その理由は、X11 転送用にディスプレイ変数を正しい状態に保ちたいのですが、スクリプトをトリガーするために、Screen が別のコンピューターに再接続されたことを検出する必要があるからです。
ありがとう。
答え1
screen -S foo -X setenv DISPLAY "$DISPLAY"; screen -S foo -rd
アタッチする前に、 を実行してプロセスの環境を変更できますscreen
。これは既存のウィンドウには影響しません。
プロンプトが表示されるたびに、更新されたDISPLAY
(および などのその他の関連変数)をチェックするようにシェルを構成することもできます。(つまり、セッションを接続したときにシェルがプロンプトを表示していた場合は、 を 1 回押す必要がある可能性があります。) bash は各プロンプトを表示する前に 評価 します。 zsh は各プロンプトを表示する前に 関数を実行します。 たとえば、必要な環境割り当てをスクリプトに記述した場合(12345 は screen プロセスの pid、はセッション名)、次のようなスクリプトを使用できます(zsh の場合、テストされていません。bash でフォークせずに済むとは思えません)。XAUTHORITY
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
一部のオペレーティング システムでは、またはから実行できるもう 1 つのprecmd
操作は、親プロセスの環境を読み取ることです (これは、screen プロセスの環境を更新していることを前提としています)。たとえば、Linux で zsh を使用する場合 (screen で実行している場合にのみ実行してください) は、次のようになります。
precmd () {
local record
while read -r -d $'\0' record /proc/$PPID/environ; do
case ${record%%=*} in
DISPLAY|XAUHORITY) export $record;;
esac
done
}
技術的には、デバッガーを使用して別のプロセスの環境を変更することができます。ただし、プログラムの内部データ構造がカーネルによって保持されているデータと一致しないため、そのプロセスがクラッシュする可能性が高くなります。
画面ウィンドウ内で ssh を実行する場合、これらの解決策はどれも役に立たないことに注意してください。
答え2
最終的に望むことは実行できません。接続時に screen でスクリプトを実行できたとしても、子プロセスの環境を変更することはできません。
答え3
Giles の解決策は最も一般的なものだと思いますが、欠点が 2 つあります。(1) 再アタッチ後にコマンドを実行するまで機能しない、(2) コマンドが新しいコマンド プロンプトごとに実行される (CPU サイクルを無駄にするのは嫌なので、仕方ありません)。代替案もありますが、これも完璧ではありません。screen
以前のウィンドウとは異なるサイズの端末に再アタッチすると、シェルに信号がscreen
送信され、これをトラップできます。SIGWINCH
trap some_function SIGWINCH
私は、この事実を利用して、切り離された端末を再接続するときに SSH_AUTH_SOCK と関連変数の書き換えを処理するシェル スクリプト (.bashrc とともにソース化される) を作成しました。プロジェクトはここで参照できます。https://gitlab.com/otheus.uibk/bashrc-ssh-agentスクリプトは簡単に変更でき、PROMPT_COMMAND と統合することもできます。
screen
再接続時に SIGWINCH を強制するオプションを追加して更新できるでしょうか? 現在、4.1.0 (RedHat 7 に同梱) を使用していますが、現在のバージョンは 4.6 です。