Bash(「Bourne Again SHell」の略)は、Unixライクなオペレーティングシステム向けに開発された対話型コマンド インタプリタおよびコマンド 言語です。フリー ソフトウェア財団によってサポートされ、1989 年に Brian Fox によってGNU プロジェクトのために作成されました。Bourneシェルやその他のプロプライエタリなUnix シェルの完全なフリー ソフトウェア代替として設計されています。[ 5 ] 広く採用された Bash は、多くのLinuxディストリビューションのデフォルトのログインシェルとして一般的に使用されています。[ 6 ]また、シェル スクリプト と呼ばれるファイルからのコマンドの実行もサポートしており、自動化を容易にします。sh
Bash コマンド構文は、 Bourne シェルの構文の上位互換であり、Bash 構文のすべての基本機能はそこからコピーされています。そのため、Bash は Bourne シェルのスクリプトの大部分を修正せずに実行できます。その他のアイデアは、 C シェル、その後継であるtcsh、およびKorn シェルから借用されています。[ 7 ] ほぼすべての最新のオペレーティングシステムで使用できるため、さまざまなコンピューティング環境で汎用性の高いツールとなっています。
シェルへの入力言語は、まず文字レベルで認識される。[ b ]
— IEEEおよびThe Open Group
$ printf '<newline>: <%b>\n' $'\n' <newline>: < > $ printf '<tab>: <%b>\n' $'\t' <tab>: < > $ printf '<space>: <%s>\n' " " <space>: < > $ printf '<NUL>: <%b>\n' $'\0' <NUL>: <>文字の並びは「文字列」または「文字列リテラル」と呼ばれます。Unix 系オペレーティングシステムでは、ヌル文字やスラッシュ/などの一部の文字を除き、印刷可能な文字と印刷不可能な文字を含むすべての文字をファイル名に使用できます。また、すべての文字列は大文字と小文字を区別します。[ c ]
Bashは、他の多くのプログラミング言語と同様に、ゼロベースの番号付けを使用します。
Controlキーと他のキーの組み合わせによる機能はGNU Readlineによって提供されており、対話モードでのみ利用可能です。特定のキーの組み合わせにより、ユーザーはBashを操作してタブ補完を使用したり、コマンド履歴を検索したりできます。
一部のキーの組み合わせにより、ユーザーはターミナルエミュレータを操作して、ターミナルウィンドウ内でカーソルを移動したり、エミュレータプログラムを制御したりすることもできます。[ 10 ]デフォルトでは、Bash のこれらのキーの組み合わせはEmacs のものと同じです。[ d ]
コントロールコードのデフォルトのキーバインドは以下のとおりです。
Bash がコマンド行全体を読み込むと、文字列全体がトークンに分割されます。 「トークン」はメタ文字を使用して識別され、メタ文字 を使用して互いに区切られます。
Bash 5.3の時点では、10個のメタ文字はスペース、タブ、改行文字に加え、以下の文字です。|&;()<>
「空白」はすべて引用符で囲まれていないメタ文字で構成され、「演算子」はそれぞれ少なくとも1つの引用符で囲まれていないメタ文字を含み、「単語」は引用符で囲まれていないメタ文字を一切含まないものとします。
実際には、Bashはコマンド文字列全体を、メタ文字を含むトークンまたはトークンのグループと、メタ文字を含まないトークンまたはトークンのグループ( 「単語」と呼ばれる)に分解します。そこからさらに単語を、コマンド名、変数代入文など、より具体的で意味のある要素に分解します。
2つの空白はスペースとタブです。
制御演算子は制御機能を実行します。これらは、改行、または次のいずれかになります: ||、&&、&、;、;;、;&、;;&、|、、。|&()
リダイレクト演算子は、入力または出力ストリームをリダイレクトします。これらには<、、、、、およびが含まれます。>&><<<<<
単語とは、シェルによって単一の単位として扱われる(メタ文字以外の)文字のシーケンスのことです。予約語とは、シェルにとって特別な意味を持つ単語の一種です。 [ f ]
名前は、予約語とは異なる単語の一種です。名前は、(A)文字、アンダースコア、数字のみで構成され、(B)文字またはアンダースコアで始まり、(C)数字で始めることはできません。識別子とも呼ばれる名前は、変数や関数の名前付けに使用できます。
22個の「予約語」(文字または単語)のうち、16個は以下のとおりです。
'!' '[[' '{' ']]' '}' case in esac for do done if then elif else fi ... 名前には文字のみを含めることができますABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_。
以下のコマンド文字列の例では、メタ文字の上にはカンマ (,) が、予約語の下にはキャレット ( ^)が、その他のトークンの下にはバッククォート ( `)がそれぞれ配置されています。
$ #, , , ,, , ,, , $ if echo foo ; then bar = abc ; fi $ # ^^ ```` ``` ^^^^ ``````` ^^「サブシェル」とは、現在実行中のシェルによって初期化された、シェルの追加インスタンスのことです。「親」シェルがサブシェル、つまり「子」シェルを作成すると、親シェルの環境情報の正確なコピーが再作成され、サブシェルの環境となります。
Bashでは、算術以外のコンテキストでは、コマンド文字列全体を単一の括弧で囲むことで、サブシェルの使用を強制できます。
$ echo foo ; ( echo foo ) foo fooこの単純なケースでは、前述の 2 つのコマンドは同等ですが、サブシェルを使用すると、予期しない副作用が発生する可能性があります。サブシェルの初期化を引き起こす構文には、さまざまな形式があります。サブシェルの初期化を引き起こす演算子の例を以下に示します(網羅的なリストではありません)。
()例えば、はサブシェルを初期化します。$ (プログラム引数argb )A | Bパイプライン内の各コマンドごとに1つずつ、複数のサブシェルを初期化します。$ program1 abc def | program2 -abc Bashは変数と配列をデータ構造として提供しており、それぞれに多数の種類が用意されているものの、CやJavaなどの他の言語と比較すると、データ構造は比較的単純です。すべてのデータは文字列としてメモリに格納されます。
単語の先頭にドル記号($)を付けると、その単語は変数名または配列名であることを示します。ドル記号/変数名構文は二重引用符で囲むことを常に推奨します。この方法により、パラメータが保持する値が意図しない副作用から保護されます。
変数名を波括弧で囲むことは、{}可読性と変数と配列間の一貫性を保つために推奨されます。変数を記述する際、波括弧は省略可能で、角括弧は構文エラーとなります。パラメータ名は常に等号の左側に、値は常に右側に記述します。
構文を使用して変数に代入しますname=value。
変数を使用するには、構文$nameまたは を使用します。${name}これは、変数に割り当てられた値に展開されます。
後者の構文は、特定の名前に対して、意図しない副作用を防ぐために使用する必要があります。たとえば、$10はとして解析される${1}0ため、を使用すると、${10}意図したとおりに解析されます。
位置パラメータは、通常、bashスクリプトに渡され、$1から始まる番号の変数で表されます。特殊パラメータは句読点文字で示されます。たとえば、 は、"$@"最初の位置パラメータから最後の位置パラメータまでのリストに展開され、それぞれが引用符で囲まれ、スペースで区切られます。[ g ]
環境変数はすべて大文字で表記されます。環境変数には、UNIX 変数(例: )LESS_SIGUSR1や Bourne シェル変数(例: )が含まれますHOME。スクリプト変数はすべて小文字またはキャメルケースで表記されます。これは慣例にすぎず、export環境変数にするためにコマンドに渡す変数はどれでも構いません。
配列は複数の値を保持するデータ構造です。[ h ]
配列は、変数名の末尾に角括弧を付け、さらにその中に波括弧を置きます。配列を記述する際には、波括弧と角括弧の両方が必要です。
配列は構文を使用して代入されます。使用例に応じて、またはまたはname=( one or more elements )を使用して展開されます。${quux[@]}${quux[*]}${quux[1]}
各パラメータの種類は、特定の命名規則によって区別されます。[ i ]
Bash 4.0以降、Bashは連想配列もサポートしています。[ 2 ]
この記事では、このセクションの変数の例として、${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変数にリストされているディレクトリと現在の作業ディレクトリです。[ 12 ]
$ # [コマンド位置] [オプション] [引数] $ # ,--^ ,------------^ ,----^ $ declare -p USER BASH_VERSION declare -x USER="liveuser" declare -- BASH_VERSION="5.2.37(1)-release"ユーザーアカウントは、人間ユーザーとプログラムユーザーの両方に対して作成できます。Unix系オペレーティングシステムには、「特権ユーザー」と「一般ユーザー」の2種類のユーザーが存在します。rootやオペレーティングシステムのカーネルなどの特権ユーザーは、マシン上であらゆる操作を実行できます。一方、非特権ユーザーは様々な制限を受けます。
対話型シェルセッションがユーザー入力を待機しているとき、デフォルトでは特定の文字列が画面に表示されます。Bash では、この待機文字列の値はシェル変数$PS1に格納されます。一般ユーザーの場合、 の一般的なデフォルト値は$PS1ドル記号 ( $ ) です。[ j ]スーパーユーザー の場合、一般的なデフォルト値はハッシュ記号 ( # )です。
$ sudo --login --user root [sudo] liveuser のパスワード: # umask 077 # echo bob > /home/liveuser/names.txt # exit $ grep -e bob ./names.txt grep: ./names.txt: 権限が拒否されましたほとんどのユーザーはシェルを対話型コマンドインタープリタだと考えているが、実際には各ステートメントがコマンドを実行するプログラミング言語である。コマンド実行の対話性とプログラミング性の両方を満たす必要があるため、シェルは設計だけでなく歴史によっても形作られた奇妙な言語である。[ 13 ]
BashはC言語で書かれています。モジュール式スタイルは、優れたスタイルと慎重な設計によって近似することができます。[ 14 ] これは命令型または手続き型スタイルでよく使用されます。
コマンドプロセッサであるBashは、対話モードと非対話モードの2つのモードで動作します。対話モードでは、通常、コマンドはターミナルエミュレータから読み込まれます。自動化を容易にする非対話モードでは、通常、コマンドはシェルスクリプトと呼ばれる名前付きファイルから読み込まれます。コマンドラインインターフェース(CLI)でスタンドアロンコマンドとして実行される場合、Bashはデフォルトで対話モードで新しいシェルを開きます。
シェルスクリプトは、コード(多くの場合コマンド)を含むテキストファイルであり、バッチ処理において特定のインタプリタによって非対話モードで読み取られ、実行されることを意図しています。ユーザーとのやり取りは一切不要です。インタプリタ型スクリプトは、ソースコードをコンパイルする必要のないプログラムです。関連するソースコードはすべてスクリプト内に含まれています。スクリプトインタプリタとして機能するプログラムは数多くあり、Perl、AWKなどが挙げられます。インタプリタ型スクリプトは、多くの場合Unixシェル向けに作成されます。
実行可能なシェルスクリプトの最初の行の最初の2文字は、シェバンと呼ばれるもので始まります。これは文字通り、ハッシュ記号(#)とバン記号(!)が並んでいるものです。
$ cat ./example.sh # ! /bin/env bash echo fooスクリプトがコマンドライン上でスタンドアロンプログラムとしてユーザーによって実行されることを意図している場合、それは「実行可能ファイル」と呼ばれます。慣例として、実行可能な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 foosourcesource、または同義のコマンドを使用すると.、Bash は名前で指定された任意のテキストファイルからシェルコマンドを読み込んで実行します。[ k ]
Bash は、オプションを使用して、対話モードと非対話モードの両方でログイン シェル、つまり「セッション リーダー」として実行できます--login。「ログイン」にはユーザー認証が必要です。そのため、ユーザー セッションごとにログイン シェルは 1 つしか存在しません。GNU/Linux では、ユーザーのログイン シェルは /etc/passwd ファイルで識別されます。
$ awk -F ':' '$1 ~ /root/' /etc/passwd root:x:0:0:Super User:/root:/bin/bash人間ユーザーがログインセッションを開始する場合、この手順は多くの場合、グラフィカルユーザーインターフェース(GUI)で行われます。ユーザーがターミナルエミュレータを開くと、エミュレータはユーザーのログインシェルの非ログインインスタンスを実行します。
ターミナルエミュレータ内からシェルセッションをログアウトするには、 exitコマンドを使用するか、Bash ではデフォルトで+キーを押します。 Ctrld
sourceファイルBash が起動すると、sourceさまざまなドットファイル(以下のリストを参照) 内のコマンドを実行するために使用します。[ 15 ]これらのドットファイルは、シェル スクリプトとは異なり、通常は実行権限もハッシュ バン も有効になっていません。デフォルトでは、Bash は、次の条件に応じて、やや異なる一連のファイルを異なる順序で読み込みます。[ l ]
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 仕様を実装したシェルシステム アプリケーション./myscript.shであればどれでも実行可能です。そのため、POSIX 準拠のスクリプトは、POSIX 規格を実装した Unix または Unix ライクなオペレーティングシステム ( Linux、OpenBSD、Oracle Linux、HP-UXなど) で正常に実行できると合理的に期待できます。これらのスクリプトは、そのままの状態で、それ以上の変更を加えることなく「移植可能」とみなされます。シェルとコマンドライン ユーティリティに適用される POSIX の部分は、端末と端末エミュレータが移植可能とみなされるためにどのように動作すべきかをさらに規定する、より大きなPOSIX 規格群のサブセットです。
BashがPOSIXモードで動作している場合、利用できる機能は少なくなりますが、生成されたコードはより多様なオペレーティングシステムで実行できます。
sh対話型シェルの初期化時に POSIX モードを有効にするには、Bash を、bash --posixまたは のいずれかとして実行しますbash -o posix。[ m ]
スクリプトを POSIX モードで初期化するには、ハッシュバン#!/usr/bin/env shまたは移植性の低いを使用します#!/bin/sh。Bash のインスタンスが POSIX モードで動作している場合、環境変数$POSIXLY_CORRECTが定義され、環境変数の値にSHELLOPTSは文字列posixが含まれます。
$ declare -p POSIXLY_CORRECT SHLVL bash: declare: POSIXLY_CORRECT: 見つかりませんdeclare -x SHLVL="1" $ bash -o posix $ declare -p POSIXLY_CORRECT SHLVL declare -- POSIXLY_CORRECT="y" declare -x SHLVL="2"POSIXで規定されていないBashの機能の全リストは相当なものです。[ 17 ] 以下はその一部です。
$@POSIXではありません[[...]]、POSIX に準拠していません。 [...]そしてtestPOSIXです((...))POSIX に準拠していません $((...))POSIXですkernel{,-headers}POSIXではありませんlocal組み込み関数はPOSIXに準拠していません<(...)POSIXではありませんenable-s$ enable -s | wc --lines 16 $ enable | wc --lines 61enable関数自体はPOSIX準拠ではありません.コマンドsourceは同義です。 .(つまり「ドット」)組み込み関数はPOSIXですが、source関数はPOSIXではありません$EPOCHSECONDSん$EPOCHREALTIME最新のUnix系オペレーティングシステムで利用可能で、POSIXでも規定されているシステムコマンドは、POSIXの下ではオプションフラグや関連する環境変数が少なくなる場合があります。ほとんどのコマンド(などls)は、 Bashの組み込みコマンドではなく/bin、、、またはディレクトリ(Linuxでは通常GNU coreutilsまたはBusyBoxによって提供される)にあるスタンドアロンプログラムです。/usr/bin/sbin/usr/sbin
こうした違いなどから、最新の(バージョン5の)Bashシェルスクリプトは、Bourneシェルや従来のKornシェルインタープリタではそのまま実行できることはほとんどありません。GNU/Linuxの普及に伴い、移植性を考慮したスクリプト作成は次第に少なくなっています。
Bash では有効な構文だが POSIX で規定されていないコードは「bashism」と呼ばれます。このプログラムを使用すると、スクリプトが移植性エラーなしでDebian Linuxcheckbashismsで実行できることを確認できます。 [ 18 ] Vidar Holen の別の静的リンターはHaskellで書かれており、スクリプト構文を解析して、bash、dash、ksh、および Bourne sh のいずれかまたはすべてと互換性があるかどうかを確認できます。[ 19 ]shellcheck
各シェルの構文要件はそれぞれ少しずつ異なります。たとえば、Debian のポリシーでは、スクリプト内でいくつかの拡張機能が許可されています ( dashシェルと同様)。[ 20 ]一方、 autoconfのconfigureのように、POSIX 以前の Bourne シェルをサポートすることを目的としたスクリプトでは、使用できる機能がさらに制限されます。[ 21 ]
制限付きシェルは、標準シェルよりも制御された環境を構築するために使用されます。制限付きシェルは、以下の多くの操作が許可されていないか実行されない点を除いて、bashとほぼ同じように動作します。
cd。SHELL、、、、または変数の値を設定または解除しPATHます。HISTFILEENVBASH_ENV.、、historyまたはコマンドの引数として絶対パス名を使用します。hash-p. -pまたはを使用してパス検索を指定します。command-pSHELLOPTS起動時にシェル環境から関数定義をインポートし、値を解析します。>、、、、、およびリダイレクト演算子>を使用して出力をリダイレクトし<>ます。>&&>>>exec、シェルを別のコマンドに置き換える。制限モードを有効にすると、無効にすることはできません。これらの制限は、起動ファイルが読み込まれた後に適用され、シェルスクリプトには適用されません。制限モードはほとんど使用されません。
Bash では、「特権モード」はSVR4.2 UNIX System Vシェル (1992 年頃)から継承された、あまり使用されないオプションです。 [ n ] で有効にでき、で無効にできます。[ p ]set-pset+p
特権モードが有効になっている場合、SHELLOPTSシェル変数には「privileged」という文字列が含まれます。
bash --debugger呼び出し時、または対話モードもしくは非対話モードのいずれかで有効になります。bashdb と呼ばれる別のプログラムを使用します。[ 22 ] extdebugはPOSIX モードでは利用できません。詳細についてはドキュメントを参照してください。§ デバッグも参照してください。shopt-sextdebug
Bash-4.0 では、shopt 組み込みコマンドのオプションセット (compat31、compat32、compat40、compat41 など) として指定されるシェル互換性レベルの概念が導入されました。現在の互換性レベルは 1 つだけで、各オプションは相互に排他的です。互換性レベルは、ユーザーがスクリプトを最新の機能と動作を使用するように移行する際に、新しいバージョンと互換性のない以前のバージョンの動作を選択できるようにすることを目的としています。これは一時的な解決策として意図されています。[ q ]
— GNU Bash リファレンスマニュアル
xtraceを有効にすると、簡単なデバッグ内容がターミナルに表示されます。 または で有効にでき、、または で無効にできます。これらのオプションは、コマンドラインおよびハッシュバン ( 、 など)でも使用できます。set -o xtraceset -xset +o xtraceset +xset -#!/bin/bash -x
$ bash -x $ echo $(( 2 + 2 )) + echo 4 4 $ set -- 1 2 3 + set -- 1 2 3 $ printf '<%s>\n' " $@ " + printf '<%s>\n' 1 2 3 <1> <2> <3>verbose オプションは、文字列が読み込まれると同時に、展開処理が行われる前にターミナルに文字列を出力します。ほとんど使用されません。[ r ]
コメントは、情報を明確にしたり、スクリプト作成者の意図や背景を知らない人にスクリプトやソースファイルを説明したりするための貴重な手段となり得ます。
Bash の標準コメントはハッシュ文字#で示されます。ハッシュの右側から行末までのテキストは無視されます。インラインコメントは許可されていますが、ハッシュコメントはデバッグ中に表示されません。参照: § xtrace。
コロン文字「: 」で示されるコメントは、 Thompsonシェルに由来します。コロン「: 」の右側の組み込み引数はすべて無視されます。インラインコメントはできませんが、コロンコメントはデバッグ中に表示され、パラメータはすべて展開されます。[ s ]
$ # foo を定義します$ foo = bar # インラインハッシュコメントはコマンドと同じ行に表示されます$ set -x $ # 通常のコメント (出力なし) $ : " ${ foo } " + : barbash がコマンドを実行すると、終了ステータスコード(「リターン コード」とも呼ばれます)が生成され、プログラムの実行が終了した方法に関する情報が得られます。最後に取得された終了コードの値は、シェル パラメータ「疑問符:」に格納されます$?。非算術的なコンテキスト(つまり、ほとんどの場合)では、「true」の数値または「ブール値」はゼロ(0)であり、「false」の値は 1(1)です。
システムコマンドが実行されると、その終了ステータスの意図された意味は、ほとんどの場合、manページで確認できます。通常、ゼロは成功を示し、ゼロ以外の終了ステータスは、何らかの失敗状態または部分的な成功を示します。 は ping、0、1、2 の 3 つの意味のある終了コードを持つよく知られたコマンドです。
Bashでは、算術コンテキスト内では、数値の真偽値が反転します。「真」は1、「偽」は0です。算術コンテキストは通常、構文((...))またはで識別できます$((...))。算術ステートメントが整数0に評価される場合、そのステートメントは「真」とみなされ、終了コードは1になります。ステートメントが0以外の数値に評価される場合、算術ステートメントは「偽」とみなされ、終了コードは0になります。
Linux/UNIXのコマンドの中には、ゼロとイチ以外の意味のある終了コードを提供するものはなく、Linuxには終了コードの定義に関する標準的なシステムも存在しない。
$ true ; echo $? # 終了コードは「true」を意味します0 $ false ; echo $? ; echo # 終了コードは「false」を意味します1 $ $ bash -c 'exit 99' ; printf 'exit-code: %d\n' $? exit-code: 99 $ (( 1 - 1 )) ; printf '%d\n' $? # この終了コードは「true」を意味します1 $ (( 1 + 1 )) ; printf '%d\n' $? # ...そしてこの終了コードは「false」を意味します0Bashシェルには、コマンドの実行モードとしてバッチモード(非同期)とコンカレントモード(同期)の2種類があります。バッチモード(つまり、順番に)でコマンドを実行するには、コマンドをセミコロン(; )で区切るか、別々の行に記述する必要があります。
$ command1 ; command2 $ command3 この例では、command1が終了するとcommand2が実行され、command2が終了するとcommand3が実行されます。command1のバックグラウンド実行は、実行コマンドの最後に記号& を付けることで実現できます。この場合、プロセスはバックグラウンドで実行され、すぐにシェルに制御が戻され、コマンドの実行が継続されます。
$ command1 &または、 command1とcommand2を同時に実行するには、Bashシェルで次のように実行する必要があります。
$ command1 & command2 この場合、command1はバックグラウンドで実行され、&記号によって制御がシェルに戻り、シェルはフォアグラウンドでcommand2を実行します。プロセスがフォアグラウンドで実行されているときに+を入力すると、プロセスを停止して bash に制御を戻すことができます。[ t ] バックグラウンドで実行されているプロセスと停止しているプロセスの両方を含むすべてのプロセスのリストは、jobs : を実行することで取得できます。Ctrlz
$ jobs [1]- コマンド1を実行中 &出力において、括弧内の数字はジョブIDを表します。プラス記号は、bgおよびfgのデフォルトプロセスを示します。「Running」および「Stopped」というテキストは、プロセスの状態を表します。最後の文字列は、プロセスを開始したコマンドです。
プロセスの状態は、さまざまなコマンドを使用して変更できます。fgコマンドはプロセスをフォアグラウンドに表示し、bg コマンドは停止したプロセスをバックグラウンドで実行するように設定します。bg とfg は、最初の引数としてジョブ ID を受け取り、操作対象のプロセスを指定できます。ジョブ ID が指定されていない場合は、jobsコマンドの出力でプラス記号で示されるデフォルトのプロセスが使用されます。killコマンドは、シグナルを送信してプロセスを早期に終了するために使用できます。ジョブID はパーセント記号の後に指定する必要があります。
$ sleep 100 & [1] 4904 $ kill %1 $ jobs [1]+ 終了 sleep 100ジョブ制御(「モニターモード」とも呼ばれる)は、対話型シェルではデフォルトで有効になっており、無効にすることができます。set+m
シグナリングは、プロセス間通信(IPC)の手段の一つです。コマンドラインプロセスが実行中にフリーズしたように見える場合があります。このような場合、どのプロセスがブロックされているかを特定し、問題のあるプロセスを手動で終了させる必要が生じることがあります。
対話型端末では、通常、+ キーを押して現在のフォアグラウンドプロセスを終了し、ユーザープロンプトに制御を戻すか、+ キーを押してプロセスを一時停止するだけで十分です。プロセスをキャンセルしようとしても応答がない場合でも、一時停止を試みると成功することがあります。その他の場合は、killプログラムを使用して IPC シグナルを送信する必要があります。この例では、2 番目の端末画面からkillコマンドを使用して、PID 4331 のプロセスを終了します。 Ctrlc Ctrlz
$ 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 # sleep プロセスが終了しました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 ("terminate") シグナルを送信します。コマンドラインユーティリティがSIGTERMに応答してシャットダウンして正常に終了するのは一般的です。(TERM とSIGTERMは同じで、すべてのシグナル名の SIG- 接頭辞は省略できます。) Bash の+シーケンスは、フォアグラウンドプロセスにSIGINT (割り込みシグナル) を送信します。 +シーケンスはSIGSTOP (停止シグナル) を送信します。[ u ] プロセスがSIGKILL を受信すると、プロセスは即座に、そして不完全に終了します。SIGKILLは最後の手段としてのみ使用することをお勧めします。 [ 23 ] SIGKILLシグナルはブロックまたは処理できません。CtrlcCtrlz
プロセスは、受信した IPC シグナルを「キャッチ」して「処理」することができます。ユーザーは、kill 組み込みコマンドを使用して、IPC シグナルを別のプロセスに「送信」することができます。ターゲット プロセスは、特定のシグナルが受信される、つまり「キャッチ」される可能性がある場合に、どのように応答するかを事前に計画するメカニズムを設定できます。ターゲット プログラムが応答する方法は、プログラムがシグナルの受信を「処理」する方法と呼ばれます。man ページには、システム コマンドがSIGHUPを受信した際に特定の情報を端末に出力する方法が示されています。たとえば、ddコマンドなどです。[ 24 ]
bash が対話型の場合、トラップがない限り、SIGTERMは無視され(対話型シェルが終了しないように)、SIGINTはキャッチして処理されます ( wait組み込み関数が中断可能になるように)。bash はSIGINTを受信すると、実行中のループから抜け出します。すべての場合において、bash はSIGQUIT を無視します。ジョブ制御が有効な場合、bash はSIGTTIN、SIGTTOU、およびSIGTSTPを無視します。[ 25 ]
kill0
— bash(1)
デフォルトでは、Bash シェルスクリプトは送信されたすべての IPC シグナルを受信して応答しますが、Bash スクリプトは組み込みのtrapを使用してシグナルをキャッチして処理することができます。[ 26 ]
$ cat ./trap-example.sh # ! /usr/bin/env bash trap umask EXIT echo bar exit 0 $ chmod 0700 trap-example.sh $ ./trap-example.sh bar 0077Bash 内からのみ GNU 拡張機能として利用できるシグナルがいくつかあります。ERR 、EXIT、RETURN、DEBUG です。これらのシグナルはデバッグに役立ちますが、シェル組み込みコマンドでのみ送信および処理できます。詳しくは「デバッグ」の項を参照してください。
echoにはさまざまな実装があります。オプションを持つものもあれば、持たないものもあります。[ v ] オプションのリストは実装間で統一されていませんが、echoとprintf はどちらも POSIX で規定されています。スクリプト作成者が変数に含まれる文字列の正確な値を知りたい場合は、 printfを使用するのが最も一貫した方法です。-e
数字を含む任意の文字を含む文字列の場合、書式指定子は%sです。
$ foo = abc bar = 123 $ printf '<%s>\n' " ${ foo } " " ${ bar } " <abc> <123>数字のみの場合は、書式指定子は%dです。
$ printf '<%d>\n' " ${ foo } " " ${ bar } " bash: printf: abc: 無効な数値<0> <123>以下の例では、フォーマット文字列から改行が省略されているため、PS1 の値は前のコマンドの出力と同じ行に表示されます。
$ printf '<%s>' " ${ foo } " " ${ bar } " <abc><123>$もう1つの非常に一貫性のある方法は、を使用することです。の出力は入力として再利用できます。ただし、すべての変数とパラメータをを使用して出力できるわけではありません。たとえば、特殊パラメータの値などです。特殊パラメータのハッシュであるは、現在定義されている位置パラメータの数を示します。declare-pdeclare-pdeclare-p"$#"
$ declare -p foo bar declare -- foo="abc" declare -- bar="123" $ set -- $ declare -p " $# " bash: declare: 0: 見つかりません対話型シェルでの入力文字列全体については…
$ declare -p #...ハッシュはBashによってインラインコメントとして解釈されます。コメントとその右側のすべてのテキストを削除すると、Bashが実行するコマンドは になります。このコマンドは、 によると、「各 NAME の値と属性」、つまり各変数を表示し、「NAME が指定されていない場合は、すべての変数の値と属性と値を表示します」。これは 100 行を超える出力になる可能性があります。declare-phelp declare
一方、printf では変数の属性を表示することはできません。§デバッグも参照してください。
$ readonly foo $ declare -p foo declare -r foo="abc" $ printf '<%s>' " ${ foo } " <abc>$設定可能な実行環境: [ w ]
シェルとセッションの起動ファイル(別名「ドットファイル」)
Bash が起動すると、さまざまなドット ファイル内のコマンドが実行されます。[ 15 ] Bash シェル スクリプトとは異なり、ドット ファイルは通常、実行権限もインタープリタ ディレクティブも有効になっていません#!/bin/bash。
以下の例は~/.bash_profileBourne シェルと互換性があり、 と に対して csh と同様のセマンティクスを提供します~/.bashrc。~/.bash_loginは、ファイル名が存在し、読み取り可能かどうかをテストする短絡評価であり、そうでない場合はの後の部分をスキップします。[ -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 起動シーケンスとは異なる順序でこれらのファイルを読み込むことができます。root ユーザーのファイルのデフォルトの内容にも問題がある可能性があり、システムがセットアップ時に新しいユーザー アカウントに提供するスケルトン ファイルにも問題がある可能性があります。Xウィンドウ システムを起動する起動スクリプトは、ウィンドウ マネージャを起動する前にユーザー環境変数を設定しようとして、ユーザーの Bash 起動スクリプトに対して予期しない動作を行う場合もあります。これらの問題は、多くの場合~/.xsession、または~/.xprofileファイルを使用して を読み込むことで解決できます。これにより、 xtermやGnome Terminal~/.profileなど、ウィンドウ マネージャから生成された Bash シェル ウィンドウが必要とする環境変数が提供されます。
標準ストリーム- STDIN、STDOUT、STDERR
エイリアスを使用すると、入力内の特定の位置にある単語を、単純なコマンドの最初の単語に置き換えることができます。エイリアスには名前と対応する値があり、これらは組み込みコマンド alias および unalias を使用して設定および解除されます。[ x ]
— GNU Bash リファレンスマニュアル
functionシェル関数は、グループに単一の名前を付けてコマンドをグループ化し、後で実行するための方法です。これらは「通常の」単純なコマンドと同じように実行されます。シェル関数の名前が単純なコマンド名として使用されると、シェルはその関数名に関連付けられたコマンドのリストを実行します。シェル関数は現在のシェルコンテキストで実行され、それらを解釈するための新しいプロセスは作成されません。[ y ]
— GNU Bash リファレンスマニュアル
set-xset-oxtraceset-set-vset-overboseset-vset-シェルが外部コマンドを探すとき、Bourne シェル変数 に依存します$PATH。$PATHには、コロンで区切られたディレクトリのリストが含まれています。 左端のディレクトリから始めて、左から右のパターンでディレクトリを選択し、一致するものが見つかるまで各ディレクトリが検索されます。 Linux では、ユーザーが追加のコマンドを見つけられるように、ディストリビューション管理者やパッケージ開発者が、ソースファイルを やその他の場所に含めることで、:エンドユーザーの の値を変更するのが一般的です。$PATH/etc/profile.d
例えば、コマンド を検索する場合chmod、内部コマンドを検討しても何も見つからない場合、Bash はディレクトリ内を検索し$PATH、検索文字列に一致するベース名を持つ最初の実行可能ファイルの絶対パスを選択します。[ 12 ]
echoにリストされているディレクトリに複数のコマンドがある場合$PATH、コマンドラインの解析と実行の過程で、デフォルトでは最初に見つかったコマンドのみが選択されます。 の 検索は遅いです。シェルは、コマンドの位置をハッシュテーブルに記憶することで、コマンドラインの実行プロセスを高速化します。ハッシュテーブルの干渉を受けずに$PATH完全な検索を実行するには、 で現在のテーブルを削除し、 であらゆる種類のコマンドを検索します。$PATHhash-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 (ディレクトリ変更) コマンドが「成功」(終了ステータスがゼロ) した./do_something場合にのみ実行され、 echoコマンドは、 cd コマンドまたはコマンドのいずれかが「エラー」(終了ステータスがゼロ以外) を返した場合にのみ実行されます。./do_something
反復: プログラムは、特定の結果に達するまで、または無期限に繰り返されることがあります。命令の各実行は「反復」です。[ 29 ]
化合物:要素または部分の結合によって形成されたもの。[ 30 ]
—メリアム・ウェブスター大学辞典
ファイル属性のテスト、文字列値と整数値の比較などを行うための組み込みコマンド:
[、[[...]]<およびとの辞書的な比較>。((...))数値評価およびテスト。これには、算術演算および数値比較のためのほぼすべての「C」言語演算子が含まれます。すべてのコマンドの終了ステータスは、特別な変数に格納されます$?。
Bash 3.0 は、 Perlに似た構文を使用してプロセス内正規表現マッチングをサポートしています。[ 32 ]正規表現マッチングは、拡張テスト構造の演算子 の右側の文字列に限定されます。[ ac ]=~[[..]]
[[${line}=~[[:space:]]*(a)?b]]つまり、「aab」、「aaaaaaab」、「xaby」、「ab」のような行の値はすべて一致し、値の中に「b」がどこかに含まれている行も同様に一致します。
コプロセスとは、coproc という予約語が前に付いたシェルコマンドのことです。コプロセスは、コマンドが '&' 制御演算子で終了したかのように、サブシェルで非同期に実行され、実行中のシェルとコプロセスの間に双方向パイプが確立されます。[ ad ]
— GNU Bash リファレンスマニュアル
単語に分割する(つまり、単語分割)
迷ったら引用![ 33 ]
— 『Linuxシェルスクリプトをマスターする』(アンドリュー・マレット著)
Bashには特定の引用ルールがあります:
'...'"..."\、および$'...'。§ 地域も参照してください。$"..."
バッククォートも参照してください`...`: § 非推奨の構文。
UnicodeおよびANSI-C引用のサポート。echo-e
$ echo kernel { ,-headers } kernel kernel-headersブレース展開(またはオルタネーション)は、 Cシェルからコピーされた機能です。これは、一連の代替組み合わせを生成します。[ ae ] 生成された結果はファイルとして存在する必要はありません。展開された各文字列の結果はソートされず、左から右への順序が保持されます。
$ 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 file { 1 ..4 } .txt file1.txt file2.txt file3.txt file4.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}、$"..."引用構文による地域固有の翻訳。 [ ag ]
コマンド置換: 、$(...)
プロセス置換、または、システムがそれをサポートしている場合:<()>()
Bashは、`/proc/fd/`構文を使用したプロセス置換をサポートしています。この構文は、通常ファイル名が使用される箇所で、コマンドの出力(または入力)を置き換えます。(これは、対応するシステムでは`/proc/fd/`無名パイプを介して、必要に応じて一時的な名前付きパイプを介して実装されます。)<(command)>(command)
算術コマンド、((...))または算術展開、以下を含む$((...))
Bashは、外部プロセスを起動することなく整数計算(算術評価)を実行できます。そのために、((...))コマンドと展開構文を使用します。$((...))
標準入力、標準出力、標準エラーのデータストリームのリダイレクトが実行されます。
>、追記>>、<<ます、、<<<、、パラメータを入力として使用できる、および>|場合に、ファイルの上書きを強制することができます。その構文は、I/O リダイレクトを簡素化します。たとえば、演算子を使用して標準出力(stdout) と標準エラー(stderr) を同時にリダイレクトできます&>。これは、Bourne シェルの同等の ' ' よりも入力が簡単です。Bash はヒア ドキュメントをサポートしています。バージョン 2.05b 以降、Bash は演算子を使用して「ヒア ストリング」から標準入力(stdin)をリダイレクトできます。command>file2>&1<<<
#同じ行の末尾まで無視されます。[ 34 ] [ 35 ]\行末ではバックスラッシュによるエスケープも有効です。$'...'。ディレクトリスタック(pushdおよびpopd組み込み関数)機能は、対話モードでのみ利用可能です。
「タブ補完」または「コマンドライン補完」とも呼ばれるこの機能は、対話型コマンドシェル内でユーザーがキーを押すと、Bash が自動的に利用可能な補完スクリプトを使用して、部分的に入力されたプログラム名、ファイル名、変数名を提案します。 [ aj ] Bash のコマンドライン補完システムは非常に柔軟でカスタマイズ可能であり、特定のプログラムやタスクの引数やファイル名を補完する関数が同梱されていることがよくあります。Tab ↹
Bash は、組み込みの、、 およびコマンドによるプログラム可能な補完をサポートしています。[ 36 ] この機能は、2000 年にリリースされた 2.04 のベータ版から利用可能です。completecompoptcompgen
これらのコマンドにより、コマンド(インストール済みプログラムなど)、関数、変数、ファイル名に対して複雑かつインテリジェントな補完指定が可能になります。[ 37 ]
と2 つのコマンドはcomplete、使用可能なコマンドまたはオプションの引数がreadlinecompopt入力にどのようにリストされるかを指定します。バージョン 5.1 以降では、コマンドまたはオプションの完了は、通常、その名前を入力した後のキーストロークによってアクティブになります。[ 37 ] この機能は対話モードでのみ使用できます。 Tab
設定可能なプロンプト。この機能は対話モードでのみ利用可能です。
Bash の「ユーザー マニュアル」[ 11 ]は GNU プロジェクトによって提供されています。これは、man ページよりもユーザーフレンドリーなドキュメントであると見なされることがあります。「システムの/usr/share/doc/bash、 、または同様のディレクトリを参照することで、Bash に関する情報も見つけることができます。」 [ 38 ] GNU/Linux システムでは、infoプログラムが利用可能であれば、インストールに関連する GNU マニュアルのバージョンも で入手できます。[ 11 ] [ 39 ]/usr/local/share/doc/bashinfo bash
最新の技術マニュアル、つまり「manページ」は、bashの動作を理解するための権威ある解説技術文書となることを意図しています。GNU/Linuxシステムでは、インストールに関連するバージョンは通常、manプログラムから入手できます。[ 25 ]manbash
最近のバージョンの Bash では、シェル組み込みコマンドに関する情報はhelp、またはbash がインストールされているターミナルプロンプトで を実行することで確認できます。help[nameofbuiltin]man builtins
printfコマンドはenvを介して呼び出すことで、シェルの検索パスで見つかったプログラムを実行するようにし、シェルのエイリアスや組み込み関数を実行しないようにすることができます。[ 40 ]envprintf--help
異なるオペレーティングシステム上で動作するさまざまなシェルプログラム間の相互運用性を可能にする目的で、「POSIX仕様」[ 8 ]は、現代のUNIXライクなシェルの記述方法に影響を与えています。Bashは、「IEEE POSIX仕様(IEEE標準1003.1)のIEEE POSIX 「シェルとユーティリティ」部分に準拠した実装となることを意図している」[ ak ] 。 この標準の最新版(2024年)はオンラインで入手可能です。
bashの基盤となっている標準規格であるPOSIX規格、またはIEEE Std 1003.1は、特に参考になる。
「プロジェクトのメンテナーは、よくある質問を含む Bash ページも持っています」[ 38 ] [ 41 ] [ 42 ] この FAQ は Bash バージョン 5.1 時点のものであり、それ以降は更新されていません。
非公式なサポート手段としては、IRC の libera.chat の #bash チャンネルやメーリングリストが利用可能です。[ 7 ]
シェルスクリプトをrootユーザーとして実行することは、長年にわたりセキュリティ上の問題として広く批判されてきた。その理由としてよく挙げられるのは、スクリプトをrootとして実行すると、スクリプト内のバグによる悪影響がrootの高い権限によって増幅されるという点である。
よくある例として、スクリプトにコマンド `execute` が含まれているものの、変数 ` execute` が未定義のままになっている場合を考えてみましょう。Linux では、スクリプトが一般ユーザーによって実行された場合、シェルは一般ユーザーとしてコマンドを実行しようとしますが、コマンドは失敗します。しかし、スクリプトがルートユーザーによって実行された場合、コマンドは成功し、ファイルシステムが消去される可能性が高くなります。rm-rf${dir}/$dirrm -rf /
代わりに、コマンドごとにsudoを使用することをお勧めします。
「evalコマンドは非常に強力で、悪用されやすい。」[ 46 ]
「入力検証とは、データがデータクレンジングを経て、データ品質、つまり正確かつ有用であることを確認するプロセスである。」
入力検証は、情報システムのワークフローに適切な形式のデータのみが入力されるようにするために実行され、不正な形式のデータがデータベースに保持されてさまざまな下流コンポーネントの誤動作を引き起こすのを防ぎます。入力検証は、データフローのできるだけ早い段階で、できれば外部からデータを受信した直後に行う必要があります。[ 47 ]
— OWASP入力検証チートシート
2014年9月、このプログラムにセキュリティバグが発見された。これは「シェルショック」と呼ばれた。公表されるとすぐにインターネット全体でさまざまな攻撃が発生した。[ 48 ] [ 49 ] [ 50 ]
この脆弱性を悪用すると、特定のバージョンの Bash で実行可能なCGIスクリプトで任意のコードを実行できる可能性があります。このバグは、Bash が環境変数を介して関数定義をサブシェルに渡す方法に関係していました。[ 51 ]このバグは1989 年 8 月 (バージョン 1.03) からソースコード に存在しており[ 52 ]、2014 年 9 月 (バージョン 4.3) に修正されました。
バグが発見されてから間もなく、バグを修正するパッチが公開されました。最新バージョンへのアップグレードを強くお勧めします。
この脆弱性には、 CVE- 2014-6271 、CVE -2014-6277 、CVE- 2014-7169などの共通脆弱性識別子が割り当てられています。CVSS Metrics 2.xおよび3.xでは、それぞれ「高」および「重大」と評価されています。
パラメータ展開では、未設定またはnullの変数があるとスクリプトが停止する可能性があります。"${var:?}"
$ cat ex.sh # ! /bin/env bash bar="foo が定義されていません" echo "${foo:?$bar}" echo このメッセージは表示されません$ chmod 0700 ./ex.sh $ ./ex.sh ./ex.sh: 3 行目: foo: foo が定義されていませんスペースと改行を含む配列の内容を確実に出力する方法を、まず移植性の高い構文で、次にBashで同じ方法で出力します。POSIXには名前付き配列はなく、引数のリストのみが存在することに注意してください。このリストは組み込み関数setでリセットできます。"$@"
$ bash -o posix $ set -- "a" " b" " > c " $ printf ',%s,\n' " $@ " | sed 's/.*/|&|/' ' |,a,| |, b,| |, | | c ,|Bashでは、改行前のスペースの数が明確に示されることに注意してください。
$ array =( "a" " b" " > c " ) $ declare -p array declare -a array=([0]="a" [1]=" b" [2]=$' \nc ')問題が発生した際にエラーメッセージを表示する。
$ cat error.sh # ! /bin/env bash if ! ls -l /dev | grep sdz then echo エラー、行 "${LINENO}" fi $ chmod 0700 ./error.sh $ ./error.sh エラー、行 4xtraceを使用しています。errexit が有効になっていた場合、実行されませんでした。echoquux
$ cat ./test.sh # ! /bin/env bash echo foo false echo quux $ chmod 0700 ./test.sh $ bash -o xtrace -o errexit ./test.sh + echo foo foo + false $ bash -o xtrace ./test.sh + echo foo foo + false + echo quux quux注: bash の再初期化を必要としないサブシェルなど、特定の状況で$BASHPIDは異なります。$$
$ echo $ ( echo $ BASHPID $$ ) $$ $BASHPID 25680 16920 16920 16920 # | | | | # | | | \ - - $ BASHPIDサブシェル外# | | \ - - $$サブシェル 外# | \ - - $$サブシェル内# \ - - $ BASHPIDサブシェル 内bashbugという外部コマンドは、Bash シェルのバグを報告します。このコマンドを実行すると、ユーザーのデフォルトエディタが起動し、入力フォームが表示されます。フォームは Bash のメンテナー (またはオプションで他のメールアドレス) に送信されます。[ 74 ]
シェルスクリプトの機能は、1963 年の同名のマクロプロセッサにちなんで「 runcoms 」と呼ばれるファイルから始まりました。接尾辞「rc」は「runcom」の略です。 [ 75 ]「シェル」 という用語は、1964 年または 1965 年に Louis Pouzin によって造語され、1965 年の論文「シェル: システム内でプロシージャを呼び出し、連鎖させるためのグローバルツール」に登場しました。この論文では、後に多くの UNIX シェルで見られる多くの機能が説明されています。[ 76 ]文字エンコーディングの ASCII 標準は、 Request for Comments (RFC) 20と呼ばれる文書で 1969 年に定義されました。[ 77 ]
Bashの歴史における重要な出来事を以下に挙げます。[ 78 ]
シェルスクリプト用のグラフィカルインターフェースを作成できるプログラムは数多く存在する。
"$$"。 $BASH_ENVおよび$ENVファイルは処理されず、シェル関数は環境から継承されず、SHELLOPTS、BASHOPTS、CDPATH、およびGLOBIGNORE変数が環境に存在する場合は無視されます。」 [ o ]set-vecho-e"\n"[...][[[ ... ]]bcくださいawk。 $(command)`command`test [ 11 ]-aプライマリ-oと括弧で囲まれた式の使用は非推奨となっています。スクリプトではこれらを使用すべきではありません。テスト呼び出しを単一のプライマリに制限し、と-aを-oシェルの&&と\|\|リスト演算子に置き換える方がはるかに信頼性が高くなります。」 [ an ]$((...))$[...][!x][^x]^^↑[!...]\|^しかし、オープンソース プログラムに付属する構成およびインストール スクリプトはほぼすべて bash 用に書かれており、それらのスクリプトを理解するには bash を知っている必要があります。
Autoconfバージョン2.73用。
今これを学ぶことで、特に後々の多くの苦痛や悲しみを避けることができます。
では、ほとんどのユーザーがbashを使用しています。なぜなら、bashは最も人気があるからです。
Solaris 11では、以下の変更を含むユーザー環境とコマンドライン引数の変更が導入されています。シェルの変更 - デフォルトのシェルである/bin/shは、ksh93にリンクされるようになりました。デフォルトのユーザーシェルは、Bourne-again (bash)シェルです。
コンテンツプレビュー
Copyright © 2003, 2014 Apple Inc. All Rights Reserved. ... 更新日: 2014年3月10日