シェルスクリプトでは、「終了」は一般的に自発的に、または少なくとも正常に意味することを知っています。終了セッション(またはプロセスセッション内で)そして私が知っているいくつかのシャットダウンモードがあります。
1. 簡単なexit
コマンド
最初のシェルセッション(シェルセッション0)にある場合、通常シェルCLIが発生します。窓ただし、一部のサブセッション(シェルセッション1以上)にある場合、実行は通常、ユーザーを以前のセッション(たとえば1 → 0
)に戻します。
exit SOME_EXIT-CODE
2.コマンド
大きく3つ見つかりました。終了コードこの終了タイプの場合:
exit 0
(成功)。exit 1
(「ゼロ除算」などの一般的なエラーやその他の操作は許可されません.)exit 2
(Bash 4.xxのように - シェル組み込み関数の乱用、例は空の関数ですmyFunc() {}
)。
私はしばしば実行の指示としてコマンドシーケンスの終わりに追加されることがわかります。結果;時々ユニットテスト、良い:
domain="$1" && test -z "$domain" && exit 2
# Test if a user passes only one domain as a parameter, when executing this script
3. スクリプトを追加せずに終了
正しく覚えていれば、Bashスクリプトの実行が完了すると、その「終了」は実際には一般的な* nix用語で「終了」です。スクリプト自体は、ユーザーがCLIセッションで再び終了できるセッションです。ここも少しあります。終了コード、与えることができます。
私の質問
通常、シェルスクリプト、特にBashには他の「終了モード」がありますか?
答え1
「脱退」とは、通常、自発的または少なくとも成功した終了を意味する。
少なくともPOSIXテキストは使用しているようです。出口外部の理由でプロセスが終了するのではなく、自発的にプロセスを終了するためにのみ使用されます。 (例えばwait()
)信号によって終了したプロセスは成功したと見なされないため、成功した終了はその意味で「終了」でなければなりません。たとえこれらの用語が非公式にあまり厳密に使われてほしいが。
通常、シェルスクリプト、特にBashには他の「終了モード」がありますか?
モデル場合によっては(たとえば)特定の技術的意味がありますが、ここでは考えることがchmod()
できないので、何を求めるのかわかりません。
それにもかかわらず、シェルスクリプトは少なくとも次の理由で終了する可能性があります。
- スクリプトは、スクリプトが終了するまで実行されます。スクリプトの終了状態は、最後に実行されたコマンドの終了状態です。
- スクリプトが実行されます。
exit
組み込みコマンド議論の余地はありません。同様に、終了状態は最後に実行されたコマンドの状態です。 - このスクリプトは
exit
パラメータを使用してコマンドを実行します。終了状態はパラメーターの値です。 - スクリプトが設定されていない変数を参照します。
set -u
/set -o nounset
実施中です。終了ステータスはシェルによって異なりますが、ゼロではありません。 (Bashはそれを使用しているようです127
.) (*) - このスクリプトは失敗したコマンドを実行します。
set -e
/set -o errexit
実施中です。終了状態は、失敗したコマンドの終了状態です。(しかし見てくださいバッシュFAQ 105質問についてset -e
。 ) - スクリプトで構文エラーが発生しました。シェルの終了状態はゼロではありません。 (Bashはそれを使用しているようです
1
.) (*) - スクリプトを受信しましたシグナルこれにより終了します。すべてのシグナルが終了するわけではなく、シグナルを無視するか、次のようにスクリプトでハンドラーを設定できます。
trap
組み込みコマンド。これは信号をCtrl-C送信するeqヒットにも当てはまります。(*)SIGINT
技術的に言えば、事例1~6の場合、シェルプロセススクリプトの実行は自動的に終了します(つまり、プロセス呼び出しexit()
)。一方、相手の立場ではスクリプトそれ自体、または文法的エラーによる終了は、非自発的と呼ばれる可能性が高いですset -e
。set -u
ただし、シェルスクリプトはシェルインタプリタと同じではありません。
1〜3では、成功した完了には0終了状態を使用し、失敗には0以外の値を使用することが慣例です。ゼロ以外の値の正確な意味は、ユーティリティによって異なります。一部は 0 と 1 のみを使用することも、他の一部は状況に応じて 0 以外の状態を使用することもできます。たとえば、grep
を使用すると1
一致するものがないことを示し、値より大きい場合は1
エラーがあることを示します。 Bashの組み込み関数は、2
誤ったオプションなどのエラーを示すためにも使用されます。同様のカスタマイズを使用すると便利ですが、スクリプト終了状態の意味を文書化する必要があります。シャットダウン状態は通常8ビットに制限されるため、範囲は〜0
です255
。
4~6では、このような状況が通常一種の失敗とみなされるため、終了状態が0ではない。 7. 終了ステータスがありません。代わりに、シグナルによってプロセスが終了すると、wait()
システムコールは問題のシグナルを示します。親プロセスがシェルの場合、通常は終了状態として表示されます128 + <signal number>
(たとえば、143
終了する子プロセスの場合)SIGTERM
。
(*スクリプトとは異なり、対話型シェルは構文エラーです。)でset -u
終了しません。SIGINT
最初のシェルセッションにいる場合、これは通常シェルCLIウィンドウを閉じます。
端末エミュレータによって開始されたプロセスが終了すると、通常は閉じます。ただし、これはシェルの機能ではなく、端末エミュレータによって異なります。端末エミュレータは、プログラムが終了したことをユーザに知らせるためにウィンドウを開いたままにすることを決定することができ、端末エミュレータでシェル以外のものを実行することもできる。
一部のサブセッションにいる場合、通常は実行によってユーザーは前のセッションに戻ります。
インタラクティブシェルを使用して別のシェルを起動すると、子シェルがシャットダウンしたときに親シェルは引き続き実行されます。しかし、繰り返しますが、これはシェルとは何の関係もありません。エディタを起動したり、インタラクティブシェルでコマンドを実行したりしても同じことが起こります。子プロセスが終了すると、親シェルは引き続きユーザーのコマンドを受け入れます。
SHLVL
Bash は Bash が起動するたびに 1 ずつ増加する変数を保持するため、ある意味では入れ子になったシェルの内部アイデアがあります。しかし、私は「副会議」という用語が一般的ではないと思います。何らかの形の番号付けは言うまでもありません。 (私の考えでは、.SHLVL
で初期化されているようです1
。)
答え2
出口の「モード」は実際には変わりません。
引数なしで使用すると、exit
前のコマンドの戻りコードが戻りコードとして使用されます。これがスクリプトの最後のコマンドである場合、source
スクリプトが作成されない限り、実際にはNOOPです。
exit 0
戻りコードを0
エラーではなく状態の標準終了コードであると明示的に設定します。
ゼロ以外の数字を使用すると、同じことが行われます。つまり、戻りコードを指定された値に設定します。
指示文なしでスクリプトがexit
終了すると、そのコマンドによって実行された最後のコマンドの終了コードが使用されます。
トラップにステートメントを含めると、trap '[...]' EXIT
スクリプトが実際にシャットダウンされる前にトラップが実行される(含まれているコマンドを含む)ため、そのステートメントが置き換えられます。exit
exit
答え3
0、1、2に加えて、より多くの終了コードがあります。より:
終了コードについて考えるとき、スクリプトが常に疑われる場所で終わるわけではないことを覚えておく必要があります。完了する前にシグナルによって終了するか、またはCtrl- を押すと、予期しない入力ターミネーターが終了し、予期しないシャットダウンが発生する可能性がDあります。したがって、スクリプト、特に大量のコードを返すスクリプトの正しい理解と分析が必要です。
答え4
質問を正しく理解したかどうかはわかりませんが、他の進行方法を探しているようです。終了変えるやめる?
言うように、シェル(またはシェルが実行するコマンド)を終了することができます(たとえば、対話型シェルがEoFに遭遇すると終了します。 (例:シェルの「出口2」のため、コード2で終了)
親シェルからプロセスを分離するために「nohup」(またはそのバリアント)を実行せずに親シェルが終了すると、「HUP」が表示されることがあります。
Ctrl-Cを受け取ることができます。
メモリ/CPU/何かが足りない場合があります(fd?)
kill -9のようなものを得ることもできます。 (それでも、スクリプト自体は「kill -9 $$」自体を実行できます...)
ケーシングは、左端の突然の終了のために破損したパイプの右側にある可能性があります。
より多くのケースがあるようです...
これらのそれぞれはプログラム/シェルを終了することになっており、それぞれは若干異なります(そして終了する前にいくつかのタスクを実行するか、完全に終了するのを防ぐためにいくつかをキャッチすることができます(例えば、ctrl-Cの場合はINT信号)。 )