私は主に以下のbashスクリプトを設定しています
#!/bin/bash
しかし、私は定期的に次のようなものに遭遇します
#!/bin/bash -e
#!/bin/bash -x
#!/bin/bash -ex
等々。
これらのシェバン オプションの意味と利点、および他のシェバンにも適用されるかどうかを説明できる人はいますか?
答え1
スクリプト/path/to/foo
が で始まる場合#!/bin/bash
、 を実行することは/path/to/foo arg1 arg2
を実行することと同じです/bin/bash /path/too/foo arg1 arg2
。シェバン行が の場合#!/bin/bash -ex
、 を実行することと同じです/bin/bash -ex /path/too/foo arg1 arg2
。この機能はカーネルによって管理されます。
移植可能な引数は、シェバン行に 1 つだけ指定できることに注意してください。一部の unice (Linux など) は引数を 1 つしか受け入れないため、 bash は 2 つの引数と. ではなく#!/bin/bash -e -x
、1 つの 5 文字の引数-e -x
(構文エラー)を受け取ることになります。-e
-x
Bourne シェルsh
および POSIX sh、bash、ksh、zsh などの派生シェルの場合:
-e
いずれかのコマンドが失敗した場合 (ゼロ以外のステータスを返すことで示されます)、スクリプトは直ちに終了します。-x
シェルに実行トレースを出力させます。
他のプログラムではこれらのオプションは理解されますが、意味は異なります。
答え2
bash
これらは、詳細情報を確認するために渡されるオプションですhelp set
。この場合は次のようになります。
-x Print commands and their arguments as they are executed.
-e Exit immediately if a command exits with a non-zero status.
答え3
さらに優れた、つまりよりポータブルな代替案について言及したいと思います。
#!/usr/bin/env bash
上記の例では、実行ファイルenv
を見つけるためにを使用していますbash
が、実行ファイルは必ずしも にあるわけではありません/bin/bash
。古い#!/bin/bash
スクリプトは では動作しません。ニクスOS、 例えば。
上記のようにを使用する場合、 toenv
などの引数を指定することはできません(私の知る限り)。ただし、代わりに次のようにすることができます。-e
bash
#!/usr/bin/env bash
set -e
答え4
でスクリプトを開始するか、同等に を実行すると 、スクリプト内の の行の直後にを挿入するのと同じ効果があります。#! /path/to/bash -option
bash -option /path/to/script
set -option
#!
set -x
基本的にはデバッグ専用です。通常はオンのままにしておく必要はありません。
の効果はset -e
マニュアルで説明されているよりもはるかに複雑です。より正確な説明はおおよそ次のようになります。
を呼び出した後
set -e
、未テストコマンドがゼロ以外のステータスで終了すると、シェルもその終了ステータスで終了します。
私は言うより正確なまだかなり曖昧なので、コマンドが考慮される状況のリストテスト済みは難解で予測が困難です。正確なルールはシェルごとに異なり、同じシェルでもバージョンによって変わることがあります。
set -e
するない任意のコマンドの終了ステータスがゼロ以外の場合に Bash を終了させます。
if
/elif
とthen
;の間またはwhile
/until
とdo
;の間または- 以下
!
;または ||
または&&
または が続く&
(ただし、&
対応するwait
または はfg
失敗する可能性がある)。または- が有効な
|
場合を除き、が続く。またはset -o pipefail
$( ... )
コマンドの一部として使用される場合の内部(裸の割り当てやリダイレクトではなく、失敗したfoo=$( bar )
場合は失敗しますbar
が、local foo=$( bar )
失敗しないことを意味します)または- 上記が適用される複合コマンド内、または
- どこからでも呼び出されるシェル関数内では、上記が適用されます。
複合コマンドとシェル関数への影響は再帰的です。
シェル自体はゼロ以外のステータスで終了するため、その効果はサブシェルの外に伝播する可能性があります。
例外!
は、反転された終了ステータスが無視される場合でも適用されます。
set -e
逆に、ほかのすべての非ゼロのステータス。これは、それが「失敗」を意味するか、単に「偽」を意味するかに関係なく発生します。たとえば、が最初に 0((x++))
の場合、非ゼロの「失敗」終了ステータスになりますx
。
set -e
これは非常に面倒なので、すべてのコマンドを明示的にチェックして回避するべきだという考え方もあります。
または、 を引き続き使用したい場合は、グループの前にset -e
書き込むことを忘れないでください。!
((arithmetic))