Bash (「Bourne Again SHell」の略) は、Unix系オペレーティング システム用に開発された対話型コマンド インタープリタおよびプログラミング言語です。
これは、 Bourneシェル、` sh`、その他のプロプライエタリUnixシェルの100%フリーソフトウェア代替として設計されています。[7] Bashは広く採用されており、多くのLinuxディストリビューションのデフォルトのログインシェル として一般的に使用されています。[8]
1989年にブライアン・フォックスによってGNUプロジェクトのために作成され、フリーソフトウェア財団によってサポートされています。[9]
また、シェル スクリプトと呼ばれるファイルからのコマンドの実行もサポートしており、自動化を容易にします。
Bashのコマンド構文はBourne Shellの構文のスーパーセットであり、Bash構文の基本機能はすべてBourne Shellからコピーされています。そのため、BashはBourne Shellスクリプトの大部分を変更することなく実行できます。その他のアイデアは、C Shell、その後継であるtcsh、そしてKorn Shellから借用されています。Bashはほぼすべての最新オペレーティングシステムで利用可能であり、様々なコンピューティング環境で汎用的なツールとなっています。
シェルへの入力言語は、まず文字レベルで認識されます。
— 「POSIX 1003.1-2024、2.10.1 シェル文法語彙規則」。The Open Group 基本仕様書 第8版、IEEE Std 1003.1-2024。The Open Group 。2025年8月25日閲覧。
$ printf '<改行>: <%b>\n' $'\n' <改行>: < > $ printf '<タブ>: <%b>\n' $'\t' <タブ>: < > $ printf '<スペース>: <%s>\n' " " <スペース>: < > $ printf '<NUL>: <%b>\n' $'\0' <NUL>: <>
文字の連続は「文字列」、あるいは「文字列リテラル」と呼ばれることもあります。Unix系オペレーティングシステムでは、ヌル文字やスラッシュ(/)などの一部の文字を除き、印字可能文字と印字不可能文字を含むすべての文字をファイル名に使用できます。また、すべての文字列は大文字と小文字が区別されます。[10]
Bash は、他の多くのプログラミング言語と同様に、ゼロベースの番号付けを使用します。
Ctrl+キー機能はGNU Readlineによって提供されており、対話モードでのみ利用できます。特定のキーの組み合わせを押すことで、Bashでタブ補完を使用したり、コマンド履歴を検索したりできます。
一部のキーの組み合わせは、ターミナルエミュレータを操作してターミナルウィンドウ内でカーソルを移動したり、エミュレータプログラムを制御したりすることもできます。デフォルトでは、Bashのこれらのキーの組み合わせはEmacsのものと似ています。[11]
制御コードのデフォルトのキーバインドは次のとおりです。
Viキーバインディングも利用可能で、実行することで有効にすることができます。[12] [13]set -o vi
Bash が完全なコマンドラインを読み込む際、文字列全体がトークンに分割されます。トークンはメタ文字を使用して識別され、メタ文字 によって互いに区切られます。
Bash 5.3 時点では、10 個のメタ文字は、スペース、タブ、改行に加えて、次の文字です。|&;()<>
「空白」は引用符で囲まれていないメタ文字のみで構成され、「演算子」にはそれぞれ少なくとも 1 つの引用符で囲まれていないメタ文字が含まれ、「単語」には引用符で囲まれていないメタ文字を含めることはできません。
実際には、Bash は完全なコマンド文字列を、メタ文字を含むトークンまたはトークンのグループと、メタ文字を含まないトークンまたはトークンのグループ( 「ワード」と呼ばれる)に分解します。 そこからさらに、ワードをコマンド名、変数代入文など、より具体的で意味のある部分に 分解します。
2 つの空白はスペースとタブです。
制御演算子は制御機能を実行します。制御演算子は改行文字、または次のいずれかになります:
||、、、、、、、、、、、、。&&&;;;;&;;&||&()
リダイレクト演算子は入力ストリームまたは出力ストリームをリダイレクトします。これには、、、、、<が含まれます。
>&><<<<<
ワードとは、シェルによって単一の単位として扱われる(メタ文字以外の)文字の並びです。予約語は、シェルにとって特別な意味を持つワードの一種です。 [14] 名前は予約語とは異なるワードの一種です。名前は文字、アンダースコア、数字のみで構成され、文字またはアンダースコアで始まりますが、数字で始まることはできません。名前は識別子とも呼ばれ、変数や関数の命名に使用できます。
22 個の「予約語」のうち、文字または単語である 16 個は次のとおりです。
'!' ' [[ ' ' { ' ' ]] ' ' } ' case in esac for do done if then elif else fi ...
名前には文字 のみ使用できますABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_。
次の完全なコマンド文字列の例では、メタ文字の上にはコンマが置かれ、,予約語の下にはキャレットが置かれ^、その他のトークンの下にもバックティックが置かれています`。
$ #, , ,, , ,, ,
$ if echo foo ; then bar = abc ; fi $ # ^^ ```` ``` ^^^^ ``````` ^^
「サブシェル」とは、現在のシェルインスタンスによって初期化されたシェルの追加インスタンスです。「親」シェルがサブシェル(「子」シェル)を作成すると、親シェルの環境情報の正確なコピーが再作成され、それがサブシェルの環境となります。
Bash では、算術以外のコンテキストでは、完全なコマンド文字列を単一の括弧で囲むことで、サブシェルの使用を強制できます。
$ echo foo
foo
$ ( echo foo ) foo $
この単純なケースでは、前述の2つのコマンドは同等ですが、サブシェルを使用すると予期しない副作用が生じる可能性があります。サブシェルの初期化を引き起こす構文は数多く存在します。[説明が必要]
Bashはデータ構造として変数と配列を提供しており、それぞれに多数の種類がありますが、CやJavaなどの他の言語と比較するとデータ構造は比較的単純です。[15] すべてのデータは文字列としてメモリに保存されます。
単語の先頭にドル記号($)を付けると、その単語が変数名または配列名であることを示します。ドル記号/変数名の構文は、常に二重引用符で囲むことをお勧めします。これにより、パラメータに保持される値が望ましくない副作用から保護されます。[説明が必要]
変数名を中括弧 {} で囲むことは、可読性と変数と配列間の一貫性を保つために推奨されます。変数を記述する際、中括弧は任意であり、角括弧は構文エラーとなります。パラメータ名は常に等号の左側に、値は必ず右側に記述します。
変数は構文を使用して割り当てられますname=value
変数を使用するには、$nameまたは という構文を使用します${name}。これは、変数に割り当てられた値に展開されます。
後者の構文は、望ましくない副作用を防ぐために、特定の名前に対して使用する必要があります。例えば、$10は として解析される${1}0ため、 を使用する${10}と意図したとおりに解析されます。
位置パラメータは通常、bashスクリプトに渡され、$0から始まる番号の変数で表されます。特殊パラメータは句読点文字で表されます。[15]
例えば、は、$@最初の位置パラメータから最後の位置パラメータまでのリストに展開され、「個別に引用符で囲み、スペースで区切られます」。
環境変数はすべて大文字で表記されます。環境変数にはLESS_SIGUSR1、 のようなUNIX変数や のようなBourne Shell変数が含まれます$HOME。[15]
スクリプト変数はすべて小文字、つまりCamelCaseで表記されます。
配列は複数の値を保持するデータ構造です。[16] 配列は、変数名の末尾に中括弧で囲まれた角括弧のセットで構成されます。配列を記述する際には、中括弧と角括弧が必要です。
配列は 構文を使用して割り当てられます。使用例に応じ
てまたはまたはname=( one or more elements )を使用して展開されます。${quux[@]}${quux[*]}${quux[1]}
それぞれの種類のパラメータは特定の命名規則によって区別されます。[15]
Bash 4.0以降、[17] Bashは連想配列もサポートしています。
この記事のこのセクションの変数の例には、${foo}、PID、PWD、EUID、 $$、${quux}、${zork}などがあります。
特定のプログラムの「実行」は、ユーザー (または他のプログラム) がオペレーティング システムに特定のプログラムに含まれる命令に従って動作するように要求したときに発生します。
デフォルトでは、Bash はユーザーコードを 1 行ずつ読み取り、改行文字またはセミコロンを;現在のコマンドの終了と解釈し、コマンドを順番に実行します。対話型コマンドが端末エミュレータの幅を超える場合でも、通常は入力を続けることができ、コマンドは折り返されます。コマンドを改行を超えて次の行に拡張するには、最初の行の最後の文字がエスケープされていないバックスラッシュ(行\継続を示す)である必要があります。Bash は、常に 1 つのコマンドラインの解析と実行を完了してから、次のコマンドラインの解析に進みます。
$ foo = aa bar = bb quux = cc zork = dd ; set -o xtrace
$ : " ${ foo } " ; : " ${ bar } " + : aa + : bb $ : " ${ quux } " \ > : " ${ zork } " + : cc : dd $
コマンドラインの最初の単語は「コマンドポジション」と呼ばれます。UNIXの慣習では、コマンドラインの最初の単語は常に何らかのコマンドであり、コマンドライン文字列の残りの単語は、コマンドのオプション、オプションの引数、またはコマンドが操作する何らかの入力のいずれかです。「オプション」は「フラグ」、「スイッチ」、またはより正式には「演算子」とも呼ばれます。Bashが実行するコマンドを探す際、検索するディレクトリは、$PATH変数にリストされているディレクトリと現在の作業ディレクトリです。[18]
$ # [コマンド位置] [オプション] [引数]
$ # ,--^ ,------------^ ,----^
$ declare -p USER BASH_VERSION
declare -x USER="liveuser"
declare -- BASH_VERSION="5.2.37(1)-release"
$
ユーザーアカウントは、人間またはプログラムによって作成されたユーザーに対して作成できます。Unix系OSでは、「特権ユーザー」と「通常ユーザー」の2種類のユーザーが存在します。「root」やオペレーティングシステムカーネルなどの特権ユーザーは、マシン上であらゆる操作を実行できます。一方、非特権ユーザーには様々な制限が課せられます。
対話型シェルセッションがユーザー入力を待機する場合、デフォルトでは特定の文字列が画面に表示されます。Bashでは、この待機文字列の値はシェル変数 $PS1に保持されます。一般ユーザーの場合、 の一般的なデフォルト値は$PS1ドル記号$です。[a]スーパーユーザー
の場合、 の一般的なデフォルト値はハッシュタグ ( # )
です。
$ sudo --login --user root
[sudo] liveuser のパスワード:
# vim /home/liveuser/names.txt
# exit
$ grep -e bob ./names.txt
grep: ./names.txt: 権限が拒否されました
多くのユーザーはシェルを対話型のコマンドインタープリタと考えていますが、実際には各文がコマンドを実行するプログラミング言語です。コマンド実行における対話的な側面とプログラミング的な側面の両方を満たす必要があるため、シェルは設計だけでなく歴史によっても形作られた奇妙な言語です。
— Brian W. Kernighan & Rob Pike , Kernighan, Brian W. ; Pike, Rob (1984). The UNIX Programming Environment . Englewood Cliffs: Prentice-Hall . ISBN 0-13-937699-2。
BashはC言語で書かれています。適切なスタイルと慎重な設計によって、モジュール型スタイルに近づけることができます。[19]命令型または手続き型スタイル で使用されることが多いです。
コマンドプロセッサとして、Bash は対話型と非対話型の2つのモードで動作します。対話型モードでは、コマンドは通常、端末エミュレータから読み込まれます。自動化を容易にする非対話型モードでは、コマンドは通常、今日ではシェルスクリプトと呼ばれる名前付きファイルから読み込まれます。コマンドラインインターフェース(CLI)でスタンドアロンコマンドとして実行される場合、Bash はデフォルトで対話型モードで新しいシェルを開きます。
シェルスクリプトは、コード(多くの場合コマンド)を含むテキストファイルであり、特定のインタープリタによってバッチ処理で読み取られ、非対話型モードでユーザーとのやり取りなしに実行されることを目的としています。インタープリタ型スクリプトは、ソースコードをコンパイルする必要がないプログラムです。関連するソースコードはすべてスクリプト内に含まれています。スクリプトインタープリタとして機能できるプログラムは数多くあります。例えば、 Perl、AWKなどです。インタープリタ型スクリプトは、ほとんどの場合、Unixシェル用に記述されます。
あらゆる (実行可能な) シェル スクリプトの最初の行の最初の 2 文字は、シバンと呼ばれるもので始まります。シバンとは、文字通りハッシュタグ ( # ) とバン ( ! ) の文字が並んだものです。
$ cat ./example.sh
# ! /bin/env bash
echo foo
exit
$
スクリプトがコマンドライン上でスタンドアロンプログラムとしてユーザーによって実行されることを意図している場合、それは「実行可能ファイル」と呼ばれます。慣例により、実行可能なUnixシェルスクリプト のファイル名には.shというサフィックスが付きます。シェルスクリプトの「実行」ビットは、chmodユーティリティを使用して有効にできます。
$ ls -l ./example.sh
-rw-r--r--.1 liveuser liveuser 32 Aug 3 22:33 example.sh
$ ./example.sh
bash: ./example.sh: 権限が拒否されました
$ chmod 0744 ./example.sh
$ ls -l ./example.sh
-rwxr--r--.1 liveuser liveuser 32 Aug 3 22:33 example.sh $ ./example.sh
foo $
source、または同義のコマンドを使用すると.、Bashは任意のテキストファイルからシェルコマンドを名前で読み込んで実行します。[20]
bash は、オプションを使用することで、対話型モードと非対話型モードの両方でログインシェル(セッションリーダー)として実行できます--login。「ログイン」にはユーザー認証が必要です。そのため、ユーザーセッションごとにログインシェルは1つだけ存在します。GNU/Linux では、ユーザーのログインシェルは /etc/passwd ファイルで識別されます。
$ awk -F ':' '$1 ~ /root/' /etc/passwd
root:x:0:0:スーパーユーザー:/root:/bin/bash
人間のユーザーがログインセッションを開始する場合、この手順は多くの場合グラフィカルユーザーインターフェース(GUI)で実行されます。ユーザーが端末エミュレータを開くと、エミュレータはユーザーのログインシェルの 非ログインインスタンスを実行します。
ターミナル エミュレータ内からシェル セッションからログアウトするには、exitコマンドを使用するか、Bash のデフォルトでは+を押します。 Ctrld
Bashは起動時に、source様々なドットファイル(以下のリストを参照)内のコマンドを実行します。[21]これらのドットファイルは、シェルスクリプトとは異なり、通常、実行権限もハッシュバン
も付与されていません。デフォルトでは、Bashは以下の条件に応じて、多少異なるファイルセットを異なる順序で読み込みます。[22]
sh--login、、、、--rcfile--norc--posixBASH_ENV、ENV、 そして/etc/profile~/.bash_profile~/.bash_login~/.profile~/.bash_logout、 そして~/.bashrcとりわけ。もちろん、どのスタートアップファイルでも他のファイルからコマンドを実行することができます。スタートアップファイルは、シェルの動作、端末エミュレータ、Xウィンドウシステム、ウィンドウマネージャーに影響を与える可能性があります。
POSIX IEEE 1003.1 標準は、あらゆるシェルシステム アプリケーション(bash、dash、zshなど) が準拠できる共通の定義セットを指定します。POSIXガイドラインに準拠して作成されたシェルユーザー スクリプト( ) は、POSIX 仕様を実装したあらゆるシェルシステム アプリケーションで実行できる必要があります。その結果、POSIX 準拠のスクリプトは、POSIX 標準 ( Linux、OpenBSD、Oracle Linux、HP-UXなど) を実装するあらゆる Unix または Unix 系オペレーティング システムで正常に実行できることが合理的に期待できます。これらのスクリプトは、そのままで、さらに変更を加えることなく「移植可能」であると見なされます。シェルとコマンド ライン ユーティリティに適用される POSIX の部分は、移植可能であると見なされるために端末と端末エミュレータがどのように機能すべきかをさらに指定する、より大きなPOSIX 標準のグループのサブセットです。
./myscript.sh
Bash が POSIX モードで動作している場合、利用できる機能は少なくなりますが、結果のコードはより多様なオペレーティング システムで実行できます。
対話型シェルの初期化時にPOSIXモードを有効にするには、Bashをsh、 、 のいずれbash --posixかとして実行しますbash -o posix。[23]
スクリプトをPOSIXモードで初期化するには、ハッシュバン#! /bin/env shまたは移植性の低い のいずれかを使用します#!/bin/sh。BashのインスタンスがPOSIXモードで動作している場合、環境変数$POSIXLY_CORRECTが定義され、環境変数の値には$SHELLOPTS文字列posixが含まれます。
$ declare -p POSIXLY_CORRECT
bash: declare: POSIXLY_CORRECT: 見つかりません
$ sh
$ declare -p POSIXLY_CORRECT
declare -- POSIXLY_CORRECT="y"
$
POSIXで規定されていないBashで利用可能な機能の完全なリストは膨大です。[24] 以下は部分的なリストです。
$@POSIXではない。[[...]]POSIXではない
[...]testPOSIXである((...))POSIXではない
$((...))POSIXですkernel{,-headers}POSIXではありませんlocal組み込みはPOSIXではない<(...)POSIXではありませんenable -s$ enable -s | wc --lines
16 $ enable | wc --lines
61
enable関数自体はPOSIXではない.とsource同義である。
.(つまり「ドット」)組み込み関数はPOSIXですが、sourceはPOSIXではありません$EPOCHSECONDSない$EPOCHREALTIME最新の Unix 系オペレーティング システムで使用可能であり、POSIX でも指定されているシステム コマンドには、POSIX で使用できるオプション フラグや関連する環境変数が少ない場合があります。
これらの違いやその他の違いにより、最新の(バージョン5)Bashシェルスクリプトは、Bourneシェルや旧来のKornシェルインタプリタで「そのまま」実行できることはほとんどありません。GNU/Linuxの普及に伴い、移植性を考慮したスクリプトは一般的ではなくなってきています。[23] [25]
Bashでは構文が有効だがPOSIXでは規定されていないコードは「bashism(バシズム)」と呼ばれます。プログラムcheckbashismsは、スクリプトがDebian Linuxで移植性エラーなく実行できることを確認するために使用できます。 [26] Vidar Holenのshellcheckは、 Haskellで書かれた別の静的リンターで、スクリプトの構文を解析し、bash、dash、ksh、Bourne shのいずれかまたはすべてとの互換性を確保できます。[27] 各シェルの構文要件はそれぞれ少しずつ異なります。例えば、Debianのポリシーでは、スクリプト内でいくつかの拡張機能が許可されています(dashシェルの場合と同様です)。[25]一方、 autoconfのconfigureのようなPOSIX以前のBourneシェルをサポートしようとするスクリプトでは、使用できる機能がさらに制限されています。[28]
制限付きシェルは、標準シェルよりも制御された環境を設定するために使用されます。制限付きシェルは、以下のアクションを含む多くのアクションが禁止または実行されない点を除けば、bashと全く同じように動作します。
cd。$SHELL、、、、または変数の値を設定または設定解除$PATHし$HISTFILEます。$ENV$BASH_ENV.、、historyまたはコマンドの引数として絶対パス名を使用するhash -p. -pまたはでパス検索を指定するcommand -p$SHELLOPTS起動時にシェル環境から関数定義をインポートし、値を解析します。>、、、、、およびリダイレクト演算子>を使用して出力をリダイレクトし<>ます。>&&>>>execシェルを別のコマンドに置き換えます。制限モードを有効にすると、無効にすることはできません。これらの制限は、起動ファイルの読み込み後に有効になり、シェルスクリプトには適用されません。制限モードはほとんど使用されません。
set -pset +p$SHELLOPTSbash --debugger起動時に を介して、または対話型モードまたは非対話型モード中にを介して有効化されます。これはbashdbと呼ばれる別のプログラムを使用します。[31] extdebug はPOSIXモードでは使用できません。詳細についてはドキュメントを参照してください。§ デバッグも参照してください。shopt -s extdebug Bash-4.0では、シェル互換性レベルの概念が導入されました。これは、shopt組み込み関数のオプションセット(compat31、compat32、compat40、compat41など)として指定されます。現在、互換性レベルは1つだけであり、各オプションは互いに排他的です。この互換性レベルは、ユーザーがスクリプトを移行して現在の機能と動作を利用する際に、新しいバージョンと互換性のない以前のバージョンの動作を選択できるようにするためのものです。これは一時的な解決策として意図されています。[32]
— Bashリファレンスマニュアル、6.12 シェル互換モード
xtraceを有効にすると、簡単なデバッグ内容がターミナルに表示されます。有効にするにはまたは、無効にするには 、、のいずれかを使用します。これらのオプションは、コマンドラインやハッシュバン( など)
でも使用できます。set -o xtraceset -xset +o xtraceset +xset -#!/bin/bash -x
$ bash -x
$ echo $(( 2 + 2 )) + echo 4 4 $ set -- 1 2 3 $ printf '<%s>\n' " $@ " + printf '<%s>\n' 1 2 3 <1> <2> <3> $
xtraceシェル設定はPOSIXで規定されています。§ デバッグも参照してください 。
verboseオプションは、文字列を読み込んだ後、展開が行われる前に端末に出力します。あまり使用されません。[33]
コメントは、情報を明確にしたり、スクリプト作成者の意図やコンテキストをよく知らない他のユーザーにスクリプトやソース ファイルを説明する貴重な手段となります。
Bashの標準的なコメントはハッシュ文字#で表されます。ハッシュの右側から行末までのテキストは無視されます。インラインコメントは使用できますが、ハッシュコメントはデバッグ中に出力されません。参照: § xtrace。
コロン文字(:)で表されたコメントは、Thompsonシェルに由来します。コロン( :)の右側の引数は無視されます。インラインコメントは不可能ですが、コロンコメントはデバッグ時に出力され、パラメータは展開されます。 [34]
$ # foo を定義
$ foo = bar # インラインハッシュコメントはコマンドと同じ行に出現$ set -x
$ # 通常のコメント(出力なし)$ : " ${ foo } " + : bar $
bash がコマンドを実行すると、終了ステータスコード(「リターンコード」とも呼ばれます)が生成されます。このコードから、プログラムの実行終了時の状況を把握することができます。最後に取得した終了コードの値は、シェルパラメータ「疑問符:」に保持されます$?。算術演算以外のコンテキスト(つまり、ほとんどの場合)では、「true」の数値(ブール値)はゼロ(0)で、「false」の値は1(1)です。
システム コマンドが実行されると、その終了ステータスの意味はほとんどの場合、マニュアル ページで確認できます。通常、ゼロは成功を示し、ゼロ以外の終了ステータスは何らかの失敗状態または部分的な成功を示します。
pingは、0、1、2 という 3 つの意味のある終了コードを持つよく知られたコマンドです。
Bashでは、算術コンテキスト内では数値の真理値が反転します。つまり、「真」は1、「偽」は0です。算術コンテキストは通常、構文((...))またはで識別されます$((...))。算術文が整数0に評価された場合、その文は「真」とみなされ、終了コードは1になります。算術文が0以外の数値に評価された場合、算術文は「偽」とみなされ、終了コードは0になります。
すべての Linux/UNIX コマンドが 0 と 1 を超える意味のある終了コードを提供するわけではなく、Linux には終了コードの定義に関する標準システムはありません。
$ true ; echo " $? " # 終了コードは "true" を意味します0 $ false ; echo " $? " ; echo # 終了コードは "false" を意味します1 $ $ bash -c 'exit 99' ; printf 'exit-code: %d\n\n' " $? " exit-code: 99 $ $ (( 1 - 1 )) ; printf '%d\n' " $? " # この終了コードは "true" を意味します1 $ (( 1 + 1 )) ; printf '%d\n' " $? " # ...そしてこの終了コードは "false" を意味します0
Bashシェルには、コマンド実行にバッチ(非同期)と同時(同期)の2つのモードがあります。バッチモード(つまり、連続実行)でコマンドを実行するには、コマンドを;文字で区切るか、別の行に記述する必要があります。
$コマンド1 ; コマンド2
$コマンド3
$
この例では、command1が終了するとcommand2が実行され、command2が完了するとcommand3が実行されます。実行コマンドの末尾に&シンボルを使用することで、 command1をバックグラウンドで実行できます。この場合、プロセスはバックグラウンドで実行され、すぐにシェルに制御が返され、コマンドの実行を継続できます。
$コマンド1 & $
または、 command1とcommand2を同時に実行するには、次のように Bash シェルで実行する必要があります。
$コマンド1 &コマンド2
$
この場合、command1はバックグラウンドで実行され、&シンボルによって制御がシェルに即座に戻り、シェルはフォアグラウンドでcommand2を実行します。プロセスがフォアグラウンドで実行されている間に+を入力すると、プロセスを停止してbashに制御を戻すことができます。 [35] バックグラウンドプロセスと停止中のプロセスの両方のリストは、jobsを実行することで取得できます。 Ctrlz
$ jobs
[1] - コマンド1を実行中 &
$
出力では、括弧内の数字はジョブIDを表します。プラス記号は、bgとfgのデフォルトプロセスを表します。「実行中」と「停止」というテキストはプロセスの状態を表します。最後の文字列は、プロセスを開始したコマンドです。
プロセスの状態は、様々なコマンドを使って変更できます。fgコマンドはプロセスをフォアグラウンドにし、bgコマンドは停止中のプロセスをバックグラウンドで実行させます。bg と fg は、最初の引数としてジョブIDを指定して 、処理対象のプロセスを指定できます。ジョブIDを指定しない場合は、jobsの出力でプラス記号で示されるデフォルトのプロセスが使用されます。killコマンドは、プロセスにシグナルを送信することで、プロセスを途中で終了させることができます。ジョブIDはパーセント記号の後に指定する必要があります。
$ sleep 100 & [1] 4904 $ kill %1
$ jobs [1]+ 終了 sleep 100 $
ジョブ制御 (「モニター モード」とも呼ばれる) は、対話型シェルではデフォルトで有効になっており、 を使用して無効にすることができます。
set +m
シグナリングはプロセス間通信(IPC)の手段です。コマンドラインプロセスが実行中にフリーズしてしまうことがあります。このような場合、どのプロセスがブロックされているかを特定し、問題のあるプロセスを手動で終了させる必要がある場合があります。
対話型端末では、通常、 を押して現在のフォアグラウンドプロセスを終了し、制御をユーザープロンプトに戻すか、 を押してプロセスを一時停止するだけで十分です。キャンセルしようとしたプロセスが応答しない場合は、一時停止が成功することもあります。それ以外の場合は、killプログラムを使用してIPCシグナルを送信する必要があります。この例では、別の端末画面からkillコマンドを使用して、PID 4331のプロセスを終了します。 Ctrl-c Ctrl-z
$ tty # ターミナル1 /dev/pts/0 $ whoami
liveuser $ sleep 1000 # コマンドがハングする
$ tty # ターミナル 2 /dev/pts/1 $ whoami
liveuser $ ps aux | grep -e sleep -e PID
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND liveuser 4331 0.0 0.0 230336 2312 pts/1 S+ 11:19 0:00 sleep 1000 liveuser 4333 0.0 0.0 231248 2516 pts/0 S+ 11:19 0:00 grep --color=auto -e sleep -e PID $ kill 4331 $ ps aux | grep -e sleep -e PID # スリーププロセスが終了しましたUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND liveuser 4333 0.0 0.0 231248 2516 pts/0 S+ 11:19 0:00 grep --color=auto -e sleep -e PID $
$ tty # 再びターミナル1 /dev/pts/0 $ whoami
liveuser $ sleep 1000終了しました$
Unix系オペレーティングシステムでは、ユーザーはカーネルに対し、自分が所有するプロセスにシグナルを送信するよう指示できます。ただし、一般ユーザーは特権プロセスにシグナルを送信できません。シグナルは、kill組み込みコマンドまたは同名のシステムバイナリを使用することでプロセスに送信できます。
$ whoami
liveuser
$ ps aux | awk '$2 ~ /\<1\>/' # カーネルプロセス、プロセス1の情報を見てみましょう。root 1 0.0 0.2 37140 20440 ? Ss 04:44 0:18 /usr/lib/systemd/systemd --switched-root --system --deserialize=53 rhgb $ kill -s SIGKILL 1 bash: kill: (1) - 操作は許可されていません$ type -a kill kill はシェルの組み込みコマンドですkill は /usr/bin/kill です$ /usr/bin/kill -s SIGKILL 1 kill: 1 へのシグナル送信に失敗しました: 操作は許可されていません$
最もよく使用されるシグナルは で確認できますkill -L | head -n 4。各IPCシグナルはシグナル番号に関連付けられていますが、終了コードとシグナルコードは異なるものです。プロセスにIPCシグナル9(「KILL」シグナル)を送信すると、ほぼ確実にプロセスは即座に終了しますが、プロセスが終了コード9を返す可能性は低いでしょう。
Bashでは、デフォルトで組み込みのkillはTERM(「終了」)シグナルを送信します。コマンドラインユーティリティは、SIGTERMに応答してシャットダウンし、正常に終了するのが一般的です。(TERMとSIGTERMは同じで、すべてのシグナル名のプレフィックスであるSIG-は省略できます。)BashのCtrl-cキー押下シーケンスは、フォアグラウンドプロセスにSIGINT(割り込みシグナル)を送信します。Ctrl-zキー押下シーケンスはSIGSTOP(停止シグナル)を送信します。[36] プロセスがSIGKILLを受信すると、プロセスは即座に、かつ乱雑に終了します。SIGKILLは最後の手段としてのみ使用することをお勧めします。[37] SIGKILLシグナルはブロックまたは処理できません。
プロセスは受信したIPCシグナルを「キャッチ」し、「処理」することができます。ユーザーはkill組み込みコマンドを使用して、IPCシグナルを別のプロセスに「送信」することができます。ターゲットプロセスは、特定のシグナルを受信(キャッチ)した場合の応答方法について、事前に何らかの計画を立てておくことができます。ターゲットプログラムがどのように応答するかは、プログラムがシグナルの受信を「処理」する方法と呼ばれます。マニュアルページには、SIGHUPを受信した際に特定の情報を端末に表示するシステムコマンドがいくつか記載されています。例えば、コマンドですdd。[38]
bash が対話型の場合、トラップがない場合、SIGTERMは無視されます(対話型シェルを終了させないため)。また、 SIGINTをキャッチして処理します( wait組み込み関数が割り込み可能になるため)。bash がSIGINTを受信すると、実行中のループを抜け出します。いずれの場合も、bash はSIGQUIT を無視します。ジョブ制御が有効な場合、bash はSIGTTIN、SIGTTOU、およびSIGTSTPを無視します。[39]
kill 0
— バッシュ(1)
デフォルトでは、Bashシェルスクリプトは送信されたすべてのIPCシグナルを受信して応答しますが、Bashスクリプトはtrap組み込み関数を利用してシグナルをキャッチして処理することができます。[40]
$ cat ./trap-example.sh # ! /usr/bin/env bash
トラップ umask EXIT echo バーexit 0 $ chmod 0700 trap-example.sh
$ ./trap-example.shバー0077 $
Bash 内部からのみ GNU 拡張として利用できるシグナルがいくつかあります。ERR 、EXIT、RETURN、DEBUG です。これらのシグナルはデバッグに有用であり、シェル組み込み関数によってのみ送信および処理できます。§ デバッグも参照してください。
echoには様々な実装があり、オプションを持つものもあれば、持たないものもあります。[41] echoとprintf はどちらもPOSIXで規定されています
が、オプションのリストは実装間で統一されていません。スクリプト作成者が変数に含まれる文字列の正確な値を知りたい場合、最も一貫した方法はprintfを使用することです。
-e
数字を含む任意の文字(null以外)を含む文字列の場合、書式指定子は%sです。[引用が必要]
$ foo = abc bar = 123 $ printf '<%s>\n' " ${ foo } " " ${ bar } " <abc> <123> $
数字のみの場合、書式指定子は%dです。
$ printf '<%d>\n' " ${ foo } " " ${ bar } " bash: printf: abc: 無効な数値<0> <123> $
printfでは、スクリプト作成者がフォーマット文字列に改行を含めない限り、出力に改行は含まれません。以下の例では、フォーマット文字列から改行が省略されているため、PS1の値は前のコマンドの出力と同じ行に出力されます。
$ printf '<%s>' " ${ foo } " " ${ bar } " <abc><123>$
もう一つの非常に一貫性のある方法は、 を使用することです。 の出力は入力として再利用できます。ただし、 を使ってすべての変数とパラメータを出力できるわけではありません。例えば、特殊パラメータの値などです。特殊パラメータハッシュタグ は、現在定義されている位置パラメータの数を報告します。
declare -pdeclare -pdeclare -p"$#"
$ declare -p foo bar
declare -- foo="abc"
declare -- bar="123"
$ declare -p " $# " bash: declare: 0: 見つかりません$
対話型シェルでの入力の完全な文字列については...
$宣言 -p #
...ハッシュタグはBashによってインラインコメントとして解釈されます。コメントとその右側のテキストをすべて削除すると、Bashが実行するコマンドは になります。 によると、このコマンドは「各NAMEの値と属性」、つまり各変数を表示し、「NAMEが指定されていない場合は、すべての変数の値と属性を表示」するため、出力は100行を超える場合があります。
declare -phelp declare
一方、printfは変数の属性を表示できません。§ デバッグも参照してください。
$読み取り専用 foo
$宣言 -p foo
宣言 -r foo="abc"
$ printf '<%s>' " ${ foo } " <abc> $
設定可能な実行環境: [42]
~/.bashrc~/.profileシェルとセッションの起動ファイル(別名「ドットファイル」)
Bashが起動すると、さまざまなドットファイル内のコマンドが実行されます。[21]
Bashシェルスクリプトとは異なり、ドットファイルでは通常、実行権限が有効になっておらず、のようなインタープリタディレクティブ#!/bin/bashもありません。
以下の例は~/.bash_profileBourneシェルと互換性があり、 および についてはcshと同様の意味を持ちます~/.bashrc。~/.bash_loginは短絡評価であり、 filenameが存在し、かつ読み取り可能かどうかをテストし、そうでない場合は の後の部分をスキップします。
[ -r filename ] && cmd&&
[ -r ~/.profile ] && ~/.profile # 環境設定(Bourne-sh構文のみ)if [ -n " $PS1 " ] ; then # 対話型シェルかどうか?[ -r ~/.bashrc ] && ~/.bashrc # 対話型シェルのtty/プロンプト/関数設定[ -r ~/.bash_login ] && ~/.bash_login # ログインシェルのログイン時タスクのみfi # "if"ブロックの終了
UnixおよびLinuxの一部のバージョンには、通常 ディレクトリ以下に Bash システムのスタートアップ スクリプトが含まれています/etc。Bash はこれらのファイルを標準の初期化の一部として実行しますが、他のスタートアップ ファイルは、ドキュメントに記載されている Bash スタートアップ シーケンスとは異なる順序でそれらを読み込むことがあります。ルート ユーザーのファイルのデフォルトの内容にも問題がある可能性があります。また、セットアップ時にシステムが新しいユーザー アカウントに提供するスケルトン ファイルにも問題がある可能性があります。Xウィンドウ システムを起動するスタートアップ スクリプトは、ウィンドウ マネージャーを起動する前にユーザー環境変数を設定しようとして、ユーザーの Bash スタートアップ スクリプトで予期しない処理を実行することもあります。これらの問題は、多くの場合~/.xsession、または~/.xprofileファイルを使用して を読み込むことで解決できます。これは、 xtermやGnome ターミナル~/.profileなどのウィンドウ マネージャーから生成された Bash シェル ウィンドウに必要な環境変数を提供します。
標準ストリーム- STDIN、STDOUT、STDERR
エイリアスを使用すると、入力内の特定の位置にある単語を、単純なコマンドの最初の単語として置き換えることができます。エイリアスには名前と対応する値があり、組み込みコマンド alias および unalias を使用して設定および設定解除できます。
— GNU Bashリファレンスマニュアル、第6.6章 エイリアス[43] [44] [45] [46] [47]
function
シェル関数は、コマンドをグループ化し、単一のグループ名を使用して後で実行できるようにする方法です。シェル関数は、「通常の」単純なコマンドと同じように実行されます。シェル関数名を単純なコマンド名として使用した場合、シェルはその関数名に関連付けられたコマンドリストを実行します。シェル関数は現在のシェルコンテキストで実行され、それらを解釈するための新しいプロセスは作成されません。
— GNU Bashリファレンスマニュアル、第3.3章 シェル関数[48] [49] [50] [51] [52] [53]
set -xset -o xtraceset -set -vset -o verboseset -vset -シェルが外部コマンドを探す際、Bourneシェル変数 を使用します$PATH。には$PATH、コロンで区切られたディレクトリのリストが含まれます。左端のディレクトリから左から右へと順にディレクトリを選択し、一致するものが見つかるまで各ディレクトリを検索します。Linuxでは、ユーザーが追加のコマンドを見つけられるように、ディストリビューション管理者やパッケージ開発者が、ソースファイルを やその他の場所に組み込むことで、:エンドユーザーの の値を変更するのが一般的です。
$PATH/etc/profile.d
例えば、コマンドを検索する場合chmod、内部コマンドを考慮しても何も見つからない場合、Bashはディレクトリを検索し$PATH、検索文字列に一致するベース名を持つ最初の実行可能ファイルの絶対パスを選択します。[18]
echoにリストされているディレクトリに複数のコマンドが存在する場合$PATH、コマンドラインの解析と実行のプロセスでは、デフォルトでは最初に見つかったコマンドのみが選択されます。
$PATH検索は遅くなります。シェルはコマンドの位置をハッシュテーブルに記憶することで、コマンドラインの実行プロセスを高速化します。ハッシュテーブルに干渉されることなく完全な$PATH検索を実行するには、 で現在のテーブルを削除し、 であらゆる種類のコマンドを検索します。
hash -rtype -a
$ # フルパス検索を強制する
$ PATH = ${ PATH } : ${ HOME }
$ printf 'echo script_file: "$@"\n' > ./echo
$ chmod 0700 ./echo
$ hash -r ; type -a echo echo はシェル組み込みのecho は /usr/bin/echo echo は /home/liveuser/echo $
文字列の後の方にあるコマンドを使用してコマンドラインを実行するには$PATH、絶対パスを指定するか、現在の作業ディレクトリを基準にしてパス解決をアンカーすることができます。
$ /home/liveuser/echo foo
スクリプトファイル: foo
$ ./echo bar
スクリプトファイル: bar
$
セキュリティ上の理由から、PATH 内のディレクトリは誰でも書き込み可能でないこと、または root および信頼できるユーザーのみが書き込み可能であることを確認することをお勧めします。
サブシェル: (...);
しかし、パイプラインを使用することで、複数の計算サイクルを同時に実行できるようになり、速度が大幅に向上します。パイプライン化された制御ユニットでは、複数の命令が同時に処理されますが、それぞれ異なるポイントで実行されます。1つの命令がフェッチされている間に、2つ目の命令がデコードされ、といった具合です。Unixスタイルのパイプ
ライン:|
&&)||)!)bash は「条件付き実行」コマンドセパレータを提供しており、先行コマンドによって設定された終了コードに応じてコマンドの実行を制御します。例えば、次のようになります。
$ cd " $SOMEWHERE " && ./do_something || echo "エラーが発生しました" > & 2
は、 cd (ディレクトリ変更) コマンドが「成功」(終了ステータス 0 を返した)./do_something場合にのみ実行され、 echoコマンドは、 cdまたはコマンドのいずれかが「エラー」(終了ステータス 0 以外) を返した場合にのみ実行されます。
./do_something
反復:プログラムは、無期限に、あるいは特定の結果に達するまで繰り返されることがあります。命令の各実行は「反復」と呼ばれます。[58]
化合物:要素または部分の結合によって形成されたもの。[59]
— メリアム・ウェブスター大学辞典
Bashは条件付きコマンド評価の形式もサポートしています。[ c]if ... ficase ... esac
ファイル属性のテスト、文字列と整数値の比較などを行う組み込みコマンド:
[、[[...]]高度な機能が含まれています:
<およびとの辞書式比較>;((...))数値評価とテスト。これには算術および数値比較用のほぼすべての「C」言語演算子が含まれます。すべてのコマンドの終了ステータスは特殊変数に保存されます$?。
Bash 3.0は、 Perlを彷彿とさせる構文を使用したインプロセス正規表現マッチングをサポートしています。[61]正規表現マッチングは、拡張テスト構文の演算子
の右側の文字列に制限されています。[62]=~[[..]]
[[ $line =~ [[:space:]]*(a)?b ]]つまり、「aab」、「aaaaab」、「xaby」、「ab」などの行の値はすべて一致し、値のどこかに「b」を含む行も一致します。
コプロセスとは、予約語coprocで始まるシェルコマンドです。コプロセスは、コマンドが制御演算子「&」で終了したかのように、サブシェル内で非同期的に実行され、実行中のシェルとコプロセスの間に双方向のパイプが確立されます。[63]
— Bashリファレンスマニュアル、3.2.6 コプロセス
単語に分割する(単語分割)
疑問があるときは -- 引用![64]
— Linuxシェルスクリプトのマスター、Andrew Mallett著
Bashには引用符のルールがあり、
'...'"..."\、および$'...'。§ ロケールも参照してください。$"..."
バックティックも参照してください`...`: § 非推奨の構文。
UnicodeおよびANSI-C 引用符
のサポート。echo -e
$ echo kernel { ,-headers }
kernel カーネルヘッダー
括弧展開(オルタナティブとも呼ばれる)はCシェルからコピーされた機能である。これは、複数の代替組み合わせを生成する。[65] 生成された結果はファイルとして存在する必要はない。展開された各文字列の結果はソートされず、左から右への順序が保持される。
$ echo a { p,c,d,b } e
ape ace ade abe
$ echo { a,b,c }{ d,e,f } ad ae af bd be bf cd ce cf
Bourne シェルは同じ出力を生成しない ため、ユーザーはポータブル シェル スクリプトで中括弧展開を使用しないでください。
$ # bash シェル
$ /bin/bash -c 'echo a{p,c,d,b}e' ape ace ade abe $ # 従来のシェルは同じ出力を生成しません$ /bin/sh -c 'echo a{p,c,d,b}e' a{p,c,d,b}e
括弧展開とワイルドカードを組み合わせると、まず括弧が展開され、その後、結果として得られたワイルドカードが通常通り置換されます。したがって、現在のディレクトリにあるJPEGおよびPNG画像の一覧は、次のように取得できます。
ls *. { jpg,jpeg,png } # *.jpg *.jpeg *.png に展開されます – その後、# ワイルドカードが処理されますecho *. { png,jp { e, } g } # echo は展開のみを表示します – # 中括弧内の中括弧も可能です。
中括弧展開は、交替に加えて、2つの整数または二重ドットで区切られた文字間の連続範囲にも使用できます。Bashの新しいバージョンでは、3つ目の整数で増分値を指定できます。
$ echo { 1 ..10 } 1 2 3 4 5 6 7 8 9 10 $ echo { 01 ..10 } 01 02 03 04 05 06 07 08 09 10 $ echoファイル{ 1 ..4 } .txt
ファイル1.txt ファイル2.txt ファイル3.txt ファイル4.txt $ echo { a..e } abcde $ echo { 1 ..10..3 } 1 4 7 10 $ echo { a..j..3 } adgj
括弧の展開が変数の展開 (別名、パラメータ展開とパラメータ置換) と組み合わされている場合、変数の展開は括弧の展開の後に実行されます。そのため、場合によってはeval組み込み関数 の使用が必要になることがあります。
$ start = 1 ; end = 10 $ echo { $start .. $end } # 評価順序により展開に失敗する{1..10} $ eval echo { $start .. $end } # 変数の展開が行われ、結果の文字列が評価される1 2 3 4 5 6 7 8 9 10
${foo//x/y}のために、sed 's/x/y/g'${bar##[a-zA-Z0-9]*}のためにcut -c8-、${!array[@]}、 そして${var:?error message}、パス名拡張、つまりシェルスタイルのグロビングとパターンマッチング*( 、?、を使用[...])[f]
$"..."引用構文によるロケール固有の翻訳。 [69]
コマンド置換: ,
$(...)
システムがサポートしている場合、
プロセス置換、または:<()>()
Bash は、 and構文を使用したプロセス置換をサポートしています。これにより、通常はファイル名が使用されるコマンドの出力(またはコマンドへの入力)が置換されます。(これは、それをサポートするシステムでは/proc/fd/ の名前なしパイプを通じて、必要に応じて一時的な名前付きパイプを通じて実装されます)。
<(command)>(command)
算術展開、((...))または、以下を含む
$((...))
bashは外部プロセスを起動することなく整数計算(「算術評価」)を実行できます。この目的のために、((...))コマンドと変数構文が使用されます。
$((...))
標準入力、標準出力、標準エラーデータストリームのリダイレクトが実行されます。これには以下が含まれます。
>および追加>、、<<ます、、<<<ここでは、パラメータを入力として使用できる文字列、および>場合にファイルの上書きを強制できるリダイレクト演算子。その構文はI/Oリダイレクトを簡素化します。例えば、演算子を使用して標準出力(stdout)と標準エラー(stderr)を同時にリダイレクトできます&>。これは、Bourneシェルの同等の演算子 ' ' よりも入力が簡単です。Bashはヒアドキュメントをサポートしています。バージョン2.05b以降、Bashは演算子を使用して「ヒア文字列」から標準入力(stdin)をリダイレクトできます。
command > file 2>&1<<<
#同じ行の末尾まで無視されます。[70] [71]\エスケープは行末でも有効です。$'...';>および追加>>、、<<ます、、<<<ここでは、パラメータを入力として使用できる文字列、および>場合にファイルの上書きを強制できるリダイレクト演算子。noclobberlsln無制限のサイズのコマンド履歴。[72] この機能は対話型モードでのみ使用できます。
ディレクトリ スタック (pushdおよびpopd組み込み) 機能は、対話型モードでのみ使用できます。
「タブ補完」または「コマンドライン補完」としても知られるこの機能は、ユーザーが対話型コマンドシェル内で を押すと、Bash は利用可能な補完スクリプトを自動的に使用して、部分的に入力されたプログラム名、ファイル名、変数名を提案します。[73] [4] Bash のコマンドライン補完システムは非常に柔軟でカスタマイズ可能であり、特定のプログラムやタスクの引数やファイル名を補完する関数がパッケージ化されていることがよくあります。 Tab ↹
Bashは組み込みの、、コマンドによるプログラム補完をサポートしています。 [ 74]
この機能は2000年にリリースされた2.04のベータ版から利用可能です。[75]
これらのコマンドは、コマンド(つまり、インストールされているプログラム)、関数、変数、ファイル名の複雑でインテリジェントな補完指定を可能にします。[76]completecompoptcompgen
とcompleteの2つのコマンドは、使用可能なコマンドまたはオプションの引数がreadlinecompopt入力にどのように表示されるかを指定します。バージョン5.1では、コマンドまたはオプションの補完は通常、その名前を入力した後にキーを押すことでアクティブになります。[76]
この機能は対話型モードでのみ使用できます。
Tab
設定可能なプロンプト。この機能は対話型モードでのみ使用できます。
BashのユーザーマニュアルはGNUプロジェクトによって提供されています。これは、マニュアルページよりもユーザーフレンドリーなドキュメントであると考えられることもあります。「Bashに関する情報は、システム上の/usr/share/doc/bash、 、または同様のディレクトリを参照することでも見つけることができます。」 [77]
GNU/Linuxシステムでは、infoプログラムが利用可能な場合は、インストールに関連するGNUマニュアルのバージョンも から入手できるはずです。[78] [79]/usr/local/share/doc/bashinfo bash
最新の技術マニュアル、いわゆる「manページ」は、bashの動作を理解するための権威ある解説技術文書となることを目的としています。GNU/Linuxシステムでは、インストール環境に適したバージョンは通常、manプログラムから入手できます。[78] [39] [80]man bash
最近のバージョンの Bash では、 を実行するかhelp、bash がインストールされているターミナル プロンプトで、
シェル組み込みコマンドに関する情報を見つけることができます。help [name of builtin]man builtins
printfコマンドはenv経由で呼び出すことができ、シェルのエイリアスや組み込み関数ではなく、シェルの検索パスで見つかったプログラムを確実に実行することができます。[81]env printf --help
異なるオペレーティングシステム上で動作する異なるシェルプログラム間の相互運用性を確保するため、POSIX仕様は現代のUNIX系シェルの記述方法に影響を与えています。Bashは「IEEE POSIX仕様(IEEE標準1003.1)の「シェルとユーティリティ」部分に準拠した実装となることを目指しています。」 [82] この標準の最新版(2024年版)はオンラインで入手可能です。[83]
bashのベースとなる標準としては、POSIX標準、またはIEEE Std 1003.1 [84] 以降が特に参考になります。
「プロジェクトのメンテナーには、よくある質問を含むBashページもあります」[77] [85] [86] このFAQはbashバージョン5.1時点で最新のものであり、更新されなくなりました。
非公式のサポート手段は、libera.chat の IRC、#bash チャネルを通じて利用できます。また、メーリング リストは、Bash - GNU Project - Free Software Foundation で利用できます。
シェルスクリプトをrootユーザーで実行することは、長年にわたりセキュリティ上好ましくないとして広く批判されてきました。よくある理由の一つは、スクリプトをrootユーザーで実行すると、スクリプト内のバグによる悪影響がrootの昇格された権限によって拡大してしまうことです。
よくある例として、スクリプトにコマンド が含まれているものの、変数 が未定義のままになっている場合が挙げられます。Linuxでは、このスクリプトが一般ユーザーによって実行された場合、シェルは一般ユーザーとしてコマンドを実行しようとし、コマンドは失敗します。しかし、このスクリプトがrootユーザーによって実行された場合、コマンドは成功し、ファイルシステムが消去される可能性があります。
rm -rf ${dir}/$dirrm -rf /
代わりにコマンドごとに sudoを使用することをお勧めします。
CGIスクリプトは重大な脆弱性の原因となる。[87] [88] [89] [説明が必要]
「evalコマンドは非常に強力ですが、悪用されるのは非常に簡単です。」[90]
「入力検証とは、データがデータクレンジングされ、データ品質が確保されていること、つまり正確かつ有用であることを確認するプロセスです。」
入力検証は、情報システムのワークフローに正しく形成されたデータのみが入力されていることを確認するために行われ、不正なデータがデータベースに残存して下流の様々なコンポーネントの誤動作を引き起こすことを防ぎます。入力検証はデータフローのできるだけ早い段階で、できれば外部からデータを受信後すぐに行うべきです。[91]
— OWASP 入力検証チートシート
2014年9月、 このプログラムにセキュリティ上のバグ[92]が発見されました。これは「シェルショック」と呼ばれ、公開されたことでインターネット上で様々な攻撃が発生しました[93] [94] [95]。
この脆弱性を悪用されると、特定のバージョンのBashで実行可能なCGIスクリプト内で任意のコードが実行される可能性がありました。このバグは、Bashが環境変数を介して関数定義をサブシェルに渡す方法に関係していました。[96]このバグは1989年8月(バージョン1.03)からソースコード に存在しており[97]、2014年9月(バージョン4.3)に修正されました。
バグが特定された直後に、バグを修正するパッチが公開されました。最新バージョンへのアップグレードを強くお勧めします。
この脆弱性には、共通脆弱性識別子(CVE- 2014-6271、CVE-2014-6277、CVE-2014-7169など)が割り当てられています。CVSS Metrics 2.xおよび3.xでは、このバグはそれぞれ「高」および「重大」と評価されています。
`...`$(...);-aまたは の使用、-otest[[[[ -r ./file -a ! -l ./file ][ -r ./file ] && ! [ -l ./file ];$[...]$((...))または((...))必要に応じて、^非推奨となり、 が推奨されます|。パラメータ展開により、未設定または null の変数によってスクリプトが停止する可能性があります。
"${var:?}"
$ cat ex.sh
# !/bin/bash
bar="foo is not defined"
echo "${foo:?$bar}"
echo このメッセージは出力されません
$ ./ex.sh
./ex.sh: 行 3: foo: foo は定義されていません
$
スペースと改行を含む配列の内容を、まず移植性の高い構文で確実に出力し、次にBashで同じものを出力する。POSIXには名前付き配列はなく、引数リストのみが用意されており、これは組み込み関数setでリセットできる点に注意する必要がある。
"$@"
$ # POSIXシェルの場合:
$ set -- "a" " b" " > c " $ printf ',%s,\n' " $@ " ,a, , b, , c,
Bash では、改行前のスペースの数が明確に示されることに注意してください。
$ # Bashの場合:
$ array =( "a" " b" " > c " ) $ declare -p array
declare -a array=([0]="a" [1]=" b" [2]=$' \nc ')
問題が発生した場合にエラー メッセージを印刷します。
$ cat error.sh
# !/bin/env bash
if ! lsblk | grep sdb
then
echo エラー、行 "${LINENO}"
fi
$ ./error.sh
エラー、行 130
xtraceを使用します。errexit が有効になっていた場合は、実行されませんでした。
echo quux
$ cat test.sh
# !/bin/env bash
set -x
foo=bar; echo "${foo}"
false
echo quux
$ ./test.sh
+ foo=bar
+ echo bar
bar
+ false
+ echo quux
quux
注意: bash の再初期化を必要としないサブシェルなど、特定の状況で
$BASHPIDは異なります。$$
$ echo $ ( echo $
BASHPID $$ ) $$ $BASHPID 25680 16920 16920 16920 # | | | | # | | | \ - - $ BASHPIDサブシェル外# | | \ - - $$サブシェル
外# | \ - - $$サブシェル内# \
- - $ BASHPIDサブシェル
内
bashbugという外部コマンドは、Bashシェルのバグを報告します。このコマンドを実行すると、ユーザーのデフォルトエディタが起動し、入力フォームが表示されます。入力フォームはBashのメンテナー(またはオプションで他のメールアドレス)に送信されます。[125] [126]
シェルスクリプト機能は、 1963年に登場した同名のマクロプロセッサにちなんで「 runcoms 」と呼ばれるファイルから生まれました。接尾辞「rc」は「runcom」の略です。 [127] 「シェル」 という用語は、1964年か1965年にルイ・プーザンによって造語され、1965年の論文「シェル:システム内でのプロシージャの呼び出しと連鎖のためのグローバルツール」の中で登場しました。この論文では、後に多くのUNIXシェルに見られる多くの機能が説明されています。[128] [129]文字エンコーディングのASCII標準は 、 1969年にRequest for Comments (RFC) 20と呼ばれる文書で定義されました。[130]
Bash の歴史における重要なイベントを以下に示します。
シェル スクリプトのグラフィカル インターフェイスを作成できるプログラムは多数あります。
Copyright © 2003, 2014 Apple Inc. All Rights Reserved. ... 更新日: 2014年3月10日
コンテンツプレビュー
$$
[...][[[ ... ]]
bcくださいawk。
はフリーソフトウェアであり、フリーソフトウェア財団が発行した[GNU]一般公衆利用許諾書バージョン3(またはそれ以降のバージョン)の条項に基づいて配布されています。
-2.0以降についてはtest.cを参照。
リチャード・ストールマンが、当時は制約が多かったUnixシステムの完全な代替品を作ることを決めたとき、最終的にはすべての共通ユーティリティ、特に標準シェルの代替品が必要になり、それらの代替品には適切なライセンスが必要になることを彼は認識していた。
は大文字と小文字を区別します。UNIXは大文字と小文字を区別するため、シェルスクリプトでも大文字と小文字が区別されます。
環境変数は、実行ファイルが見つかるシステム内のディレクトリをリストするため、ユーザーはコマンドの場所を入力したり記憶したりする手間が大幅に省けます。
しかし、オープンソースプログラムに付属するconfigureスクリプトとinstallスクリプトはほぼすべてbash用に書かれており、それらのスクリプトを理解するにはbashの知識が必要です。
セキュリティ上の懸念事項として、SVR4.2シェルを-pオプションなしで起動すると、実UIDと実効GIDが変更されます。
このモードでは、$BASH_ENVファイルと$ENVファイルは処理されず、シェル関数は環境から継承されず、SHELLOPTS、BASHOPTS、CDPATH、GLOBIGNORE変数は環境内にあっても無視されます。
set -v
:: SIGSTOP :: 停止、通常はCtrl + Z
は最後の手段としてのみ使用してください!
シェルでは、echoコマンドはデフォルトでこれらのコマンドオプションを認識します。Bashシェルでは、echoコマンドに-eスイッチを追加して、1行追加する必要があります。echo -e "\n"
エイリアスを使用すると、入力中の単語を、単純なコマンドの最初の単語として使用できる文字列に置き換えることができます。エイリアスには名前と対応する値があり、組み込みコマンドのaliasおよびunaliasを使用して設定および設定解除できます。
シェル関数は、コマンドをグループ化し、単一のグループ名を使用して後で実行できるようにする方法です。シェル関数は、「通常の」単純なコマンドと同じように実行されます。シェル関数の名前を単純なコマンド名として使用すると、シェルはその関数名に関連付けられたコマンドリストを実行します。シェル関数は現在のシェルコンテキストで実行され、それらを解釈するための新しいプロセスは作成されません。
今これを学んでおけば、特に後々多くの苦痛や心痛を経験せずに済むでしょう。
二重引用符で囲まれた文字列の前にドル記号
$
を付けると( など
)、文字列は現在のロケールに従って翻訳されます。gettext
インフラ
ストラクチャは、 、
、およびシェル変数
を使用して、検索と翻訳を実行します
。
$"hello, world"$LC_MESSAGES$TEXTDOMAINDIR$TEXTDOMAIN
1年半の間、GNUシェルは「ほぼ完成」していました。作者は自分が作ったものを提供すると何度も約束しましたが、一度も守られませんでした。ついに私は、彼が何かを提供するとは到底思えなくなりました。そこで、Foundationスタッフのブライアン・フォックスが現在、Bourneシェルの模倣品を実装しています。
Software Foundationの従業員は、数多くのGNUソフトウェアパッケージを開発・保守してきました。中でも注目すべきものとしては、Cライブラリとシェルが挙げられます。…GNUプロジェクトは単なるツールや開発環境の提供ではなく、これらのプログラムの開発に資金を提供してきました。私たちの目標は完全なオペレーティングシステムの構築であり、これらのプログラムはその目標達成に必要だったからです。
念のため言っておきますが、gcc、bash、そしてほとんどのGNU [bin/file]ユーティリティはMinix上で実行できます。
では、最も人気のあるシェルであるbashを使用しているため、ほとんどのユーザーがbashを使用しています。
Again Shell(bash)は、Linuxディストリビューションにインストールされる最も一般的なシェルです。
は現在までに最も人気のあるシェルであり、LinuxおよびMac OSXシステムのデフォルトシェルとなっています。
Bash 4.3までは、関数定義の末尾の文字列を環境変数の値として処理するため、リモートの攻撃者が細工した環境を介して任意のコードを実行できる可能性があります。これは、OpenSSH sshdのForceCommand機能、Apache HTTP Serverのmod_cgiおよびmod_cgidモジュール、不特定のDHCPクライアントによって実行されるスクリプト、およびBash実行から権限境界を越えて環境設定が行われるその他の状況(いわゆる「ShellShock」)を悪用した攻撃によって実証されています。
にバンドルされているbashバイナリは、長い間バージョン3.2のままです。bash v4は2009年に、bash v5は2019年1月にリリースされました。Appleがこれらの新しいバージョンに切り替えていないのは、ライセンスがGPL v3であるためです。bash v3は依然としてGPL v2です。