画面を終了する前に確認する方法(コマンドラインに終了を入力した場合)は可能ですか?
答え1
私はexit
関数でコマンドをマスクしてこの問題を解決しました。この関数は、ユーザーが画面内にあること、およびその画面プロセスに残っている唯一の子プロセスであることを確認します。
exit() {
if [[ "$(ps -o pid= --ppid "$(ps -o ppid= -p "$$")" | wc -l)" -eq 1 ]]
then
read -p "Warning: you are in the last screen window; do you really want to exit? (y/n) "
case $REPLY in
(y*) command exit "$@" ;;
esac
else
# not within screen at all, or not within the last screen window
command exit "$@"
fi
}
この機能を(bash)構成ファイルの一部として含める必要があります。つまり、~/.bash_profile
画面を起動するとき(特に指定しない限り)、$SHELL インスタンスを起動します。シェルはスクリーンプロセスの子プロセスになります。サブシェルで終了すると、上記のコードは現在のシェルの親プロセスの子プロセス数を確認します。内部から外へ:
$(ps -o ppid= -p "$$")
-=
現在のプロセスの親PIDを要求します(抑制ヘッダー行を追加)($$
)$(ps -o pid= --ppid ... | wc -l)
- 親PIDが私たちの親であるPIDリスト(ヘッダなし)を要求してから、出力された行数を計算します。
スクリーンセッションの最後の子のように見える場合は、確認メッセージが表示されます。応答が文字で始まると、関数y
は「実際の」exit
コマンドを呼び出してシェルを終了します。
最後の子プロセスではない場合、関数は実行され続け、正常に終了します。
これを開発するときに注意すべきいくつかの点があります。
if
最初は、スクリーンセッションにいるかどうかを確認するために入力STY
されたか、SHLVL
1より大きいことを確認するなど、より多くのテストを実行しました。画面はSTYを設定し、bashはSLVLを増やしますが、これらの変数のどれも読み取り専用ではないため、このテストはあまり使用するほど強力ではありません。screenも
WINDOW
変数を設定しますが、これを確認する0
ことは信頼できません。 2つのウィンドウを開き、windowを閉じて0
windowを1
最後のウィンドウとして残すことができます。デフォルトでは、EOF(通常Control+ D)を入力すると、このラッパー機能をバイパスしてシェルがすぐに終了します。私が知っている最善の解決策は、変数を
IGNOREEOF
ゼロ以外の値に設定することです。しかし、これは避けられないシェルのシャットダウンを遅らせるだけです。
上記ではbash(およびGNU procutils)関連の機能を多く使用しているので、POSIX互換のソリューションも提供したかったです。この行を、特定の親PIDを持つプロセス数をキャプチャするシナリオps
に変更します。もう1つの変更は、プロンプトとをps ... | grep -c
再作業することです。read -p
read
exit() {
parent="$(ps -o ppid= -p $$)"
if [ "$( ps -eo ppid= | grep -c "^ *${parent}\$" )" -eq 1 ]
then
printf "Warning: you are in the last screen window; do you really want to exit? (y/n) "
read REPLY
case $REPLY in
(y*) command exit "$@" ;;
esac
else
# not within screen at all, or not within the last screen window
command exit "$@"
fi
}
答え2
私はあなたがbashを使用していると仮定します。
are_u_sure(){
read -n1 -p "Are you sure to exit? [y/N] "
[ "$REPLY" != y ] && { echo; history -a; bash; }
}
trap are_u_sure EXIT
これを ~/.bashrc に追加すると、bash を終了しようとするたびにメッセージが表示されます (exit または ^D 入力)。 「y」を押さないと決して終了しません。
これにより、bashの範囲内で画面魔法を実行できるため、画面魔法にこだわる必要はありません。
この方法は非常に簡単なので、1つの欠点があります。つまり、以前に入力した変数の割り当てが失われます。しかし、おそらく私たちはそれをすることができます。とにかく、必要に応じてこのコードを変更できます。
答え3
私は私が見た他の解決策にはあまり満足していなかったので、最終的には次のようになりました(.bashrcに追加されました)。
exit_with_prompt() {
printf "Do you really want to exit screen? (y/n) "
read REPLY
case $REPLY in
(y*) command exit "$@" ;;
esac
}
export IGNOREEOF=0
[[ $(type -t exit) == "alias" ]] && unalias exit
[[ $(type -t logout) == "alias" ]] && unalias logout
if grep -q "^screen\b" /proc/$PPID/comm; then
export IGNOREEOF=2
alias exit=exit_with_prompt
alias logout=exit_with_prompt
fi
次に、これを.screenrcに追加します。
shell -$SHELL
私が普段やっていたやり方と少し反対ですね。エイリアスをオフにしてctrl-d ->終了を再び有効にしますが、bashが画面インスタンス内ですぐに実行されていることを確認します(具体的には、親プロセスコマンドが「screen」で始まり、単語の境界で始まることを確認してください)。次に、ctrl-d / EOF出口を無効にし、出口とログアウトのためのプロンプトエイリアスを使用して出口を設定します。
長い間使用していませんでしたが、これまではどのように機能するかは非常に満足しています。