bashでループwhile安全に終了

bashでループwhile安全に終了

次のようなbashスクリプトがあるとしましょう。

while :
do
    foo
done

私はこのスクリプトをコンソールで実行でき、fooを2回実行する間に発生する限りいつでも終了できます。したがってCtrl、+を押すとC(これはスクリプトを終了する別の動作かもしれません。Ctrl+Cは単なる例です)、fooを実行した後に使用可能な次のポイントで終了します。

while :
do
    foo
    if [pressed_ctrl_c]:
        break
done

ベストアンサー1

次の設定を試すことができます。

#!/bin/bash
#
INTR=
trap 'INTR=yes; echo "** INTR **" >&2' INT

while :
do
    (
        # Protect the subshell block
        trap '' INT

        # Protected code here
        echo -n "The date/time is: "
        sleep 2
        date
        read -t2 -p 'Continue (y/n)? ' YN || echo
        test n = "$YN" && echo "Asked for BREAK" >&2 && exit 90
    )
    SS=$?
    test 90 -eq $SS && echo "Matched BREAK" >&2 && break

    # Ctrl/C, perhaps?
    test yes = "$INTR" && echo "Matched INTR" >&2 && break
done
exit 0

いくつかのメモ

  • readペアは、testブロック内で保護されたコードセグメントの対話型制御を示しています( ... )
  • これはサブシェルの内部exit 90と同じですが、内部で発生します。breakサブシェルブロックの最後の直後にある行は、状態をtest 0 != $? ...キャプチャし、exit 90コードbreakが実際に望むものを実装するために使用されます。
  • サブシェルは、さまざまな終了ステータス値を使用して、さまざまな種類の所望の制御フロー(など...)breakを表すことができます。exit
  • これは、プログラムが独自のシグナルハンドラをインストールするのを防ぎません。たとえば、gdb()用の独自のハンドラをインストールします。ユーザーがセッションを中断するのを防ぐことが目標である場合は、割り込みキーを変更すると状況を難読化するのに役立ちます(下記のコードを参照)。エレガントではありませんが、おそらく効果的です。SIGINTCtrlC

端末でSIGINTキーを変更する

G=$(stty -g)                    # Save settings
test -n "$G" && stty intr ^A    # That is caret and A, not Ctrl/A

# ... SIGINT generated with Ctrl/A rather than Ctrl/C ...

test -n "$G" && stty "$G"       # Restore original settings

おすすめ記事