シェルスクリプトでは、「終了」は通常、自発的または少なくとも正常にセッションを終了することを意味することを知っています( またはプロセス セッション内)およびいくつかの異なる終了モードがあること。以下は私が知っているこれらです:
exit
コマンド私が最初のシェルセッション(シェルセッション0)にいる場合、通常はシェルCLIウィンドウが閉じますが、一部のサブセッション(シェルセッション1以降など)では、実行すると通常、ユーザーが前のセッションに戻るだけです(たとえば、_1 → 0
_)。
exit SOME_EXIT-CODE
_コマンドこのような終了で使用される3つの主要な終了コードが見つかりました。
exit 0
_(成功)。exit 1
_(「ゼロ除算」やその他の許可されない操作などの一般的なエラー)。exit 2
_(Bash 4.x.xのように-シェルビルトインの誤用。例としては、空の関数; myFunc() {}
)。これらは、実行の結果の指標としてコマンドシーケンスの最後に追加されることがよくあります。 ユニットテスト の一部として、次のようになります。
_domain="$1" && test -z "$domain" && exit 2
# Test if a user passes only one domain as a parameter, when executing this script
_
私が間違っていなければ、Bashスクリプトの実行が終了すると、その「終了」は実際には一般的な* nix用語で「終了」します。スクリプト自体は、ユーザーが終了してCLIセッションに戻るセッションです。ここでも、いくつかの終了コードが与えられる場合があります。
シェルスクリプト全般、特にBashに他の「終了モード」はありますか?
「終了」とは、通常、自発的または少なくとも正常に終了することを意味します
少なくともPOSIXテキストは、外部の理由で殺されるのではなく、プロセスの自発的な終了のためだけにexitを使用しているようです。 (例: wait()
を参照)シグナルによって強制終了されたプロセスは成功とは見なされないため、成功した終了はその意味で「終了」である必要があります。これらの用語は、非公式な使用ではそれほど厳密には使用されないと思いますが。
シェルスクリプト全般、特にBashに他の「終了モード」はありますか?
Modeは、一部のコンテキスト(chmod()
など)で特定の技術的意味を持っていますが、ここでは考えられないので、私は ' mあなたが何を求めているのか正確にはわかりません。
いずれにせよ、シェルスクリプトは 出口 少なくとも次の理由で終了します。
exit
組み込みコマンド を実行します。この場合も、終了ステータスは最後に実行されたコマンドのステータスです。exit
コマンドを実行します。終了ステータスは引数の値です。set -u
_/_set -o nounset
_ が有効な間、スクリプトは未設定の変数を参照します。終了ステータスはシェルによって異なりますが、ゼロ以外です。 (Bashは_127
_を使用しているようです。)(*)set -e
_/_set -o errexit
_ が有効なときに失敗するコマンドを実行します。終了ステータスは、失敗したコマンドのステータスです。 (ただし、_set -e
_の問題については、 BashFAQ 105 を参照してください。)1
_を使用しているようです。)(*)trap
組み込みコマンド を使用してハンドラーを設定できます。これはe.qにも当てはまります。ヒッティング Ctrl-C、SIGINT
信号を送信します。(*)技術的な意味では、ケース1から6の場合、スクリプトを実行しているシェルプロセスは自発的に終了します(つまり、プロセスはexit()
を呼び出します) 。一方、script自体の観点からは、_set -e
_、_set -u
_または構文が原因で終了しますエラーは非自発的と呼ばれることもあります。ただし、シェルスクリプトはシェルインタープリターと同じではありません。
1から3では、正常に完了するにはゼロの終了ステータスを使用し、失敗する場合はゼロ以外の値を使用するのが習慣です。ゼロ以外の値の正確な意味は、ユーティリティによって異なります。ゼロと1のみを使用するものもあれば、状況ごとに異なるゼロ以外のステータスを使用するものもあります。たとえば、grep
は_1
_を使用して一致が見つからなかったことを示し、_1
_より大きい値はエラーを示します。 Bashのビルトインも_2
_を使用して、無効なオプションなどのエラーを示します。同様のカスタムを使用すると便利な場合がありますが、スクリプトの終了ステータスが何を意味するかを文書化する必要があります。終了ステータスは通常8ビットに制限されているため、範囲は_0
_から_255
_であることに注意してください。
4から6では、状況は通常、ある種の障害と見なされるため、終了ステータスはゼロ以外です。 7では、終了ステータスはありません。代わりに、シグナルが原因でプロセスが終了すると、wait()
システムコールは問題のシグナルを示します。親プロセスがシェルの場合、通常、終了ステータスは_128 + <signal number>
_で表されます。例: SIGTERM
で終了する子の場合は_143
_。
(*スクリプトとは異なり、対話型シェルは構文エラーまたは_set -u
_またはSIGINT
のために終了しません。)
最初のシェルセッションに参加している場合、通常はシェルCLIウィンドウが閉じます。
ターミナルエミュレータは通常、開始したプロセスが終了すると閉じます。しかし、それはターミナルエミュレーター次第であり、シェルの機能ではありません。ターミナルエミュレータは、ウィンドウを開いたままにして、プログラムが終了したことをユーザーに通知する場合があります。また、ターミナルエミュレータ内でシェル以外のものを実行することもできます。
サブセッションに参加している場合、実行は通常、ユーザーを前のセッションに戻すだけです。
対話型シェルを使用して別のシェルを開始する場合、子が終了しても親シェルは続行します。ただし、これはシェルとは関係ありません。エディターを起動したり、対話型シェルからコマンドを実行したりした場合にも同じことが起こります。子プロセスが終了すると、親シェルは引き続きユーザーからのコマンドを受け入れます。
Bashは、Bashが起動するたびに1ずつ増加する変数SHLVL
を保持しているため、ある意味では、ネストされたシェルの内部的な考え方があります。しかし、「サブセッション」というフレーズはあまり一般的ではないと思います。ましてや、そのような番号付けは言うまでもありません。 (SHLVL
は_1
_で初期化されると思います。)
終了の実際には異なる「モード」はありません。
引数なしでexit
を使用すると、前のコマンドの戻りコードが戻りコードとして使用されます。これがスクリプトの最後のコマンドである場合、スクリプトがsource
dでない限り、事実上NOOPです。
exit 0
は、戻りコードを0
に明示的に設定しています。これは、エラー以外の状態の標準終了コードです。
0以外の数値を使用することは、単に同じことを実行します。つまり、戻りコードを指定された値に設定します。
スクリプトがexit
命令なしで終了すると、コマンドによって実行された最後のコマンドの終了コードが使用されます。
trap '[...]' EXIT
を実行し、トラップにexit
ステートメントを含めると、スクリプトが実際に終了する前にトラップが実行されるため(含まれているexit
コマンドを含む)、これに優先します。
0、1、および2だけでなく、さらに多くの終了コードがあります。参照:
終了コードについて考えると、スクリプトは、疑わしい場所で終了するとは限らないことを覚えておく必要があります。それらが終了する前に、それらは信号で殺されるか、または計画外の入力ターミネータが押すことによって終了する可能性があります Ctrl-D、予期しない終了を生成します。したがって、スクリプト、特に多数のコードを返すスクリプトについては、十分な理解と分析が必要です。
質問を正しく理解したかどうかはわかりませんが、プログラムが終了ではなく終了というさまざまな方法を模索しているようです。
あなたが言ったようにシェル(またはシェルによって実行されるコマンド)を終了させることができます(例:EoFを奨励するとインタラクティブシェルは終了します。実行するコマンドが不足すると(スクリプトの終わり)、シェルも終了します。または出口に遭遇した場合(例:シェルの「exit2」はリターンコード2で終了します)
親シェルが終了し、その親シェルからプロセスをデタッチするために「Nohup」(またはそのバリアント)が実行されなかった場合、「HUP」を受け取る可能性があります。
ctrl-Cを受け取ることができます
メモリ/ CPU /何か(fd?)が不足する可能性があります
キル-9またはその他を受け取る可能性があります(スクリプト自体は、たとえ奇妙な場合でも、そのように「キル-9 $$」することができます...)
シェルがパイプの右側にある可能性があります。パイプの左側が突然終了したために破損します。
そして、私はもっと多くの場合があるに違いない…。
それらのそれぞれがプログラム/シェルを終了する必要があり、それぞれが少し異なります(そして、終了する前に何かをするためにそれらのいくつかをトラップするか、完全に終了するのを防ぐことができます(ctrl-Cの場合、たとえば、INT信号をトラップすることができます) )