このチュートリアルでは、Linuxで独自のBashスクリプトを簡単に書く方法を説明します。
システム管理者として、自動化が可能な反復タスクを実行していることはよくあることでしょう。
Bash を使用すると、Bash スクリプトで好きなだけコマンドを指定することにより、システム全体のバックアップをスケジュールすることができます。
Bash を使用すると、スクリプトを実行し、有用なパフォーマンス指標をファイルまたはデータベースにダンプすることもできます。
Bash は、システム管理者にとって非常に強力なプログラミング言語です。
目次
What You Will Learn
このチュートリアルを最後まで読むと、Bash
- コマンドラインを使った Bash スクリプトの作成と実行方法、
- shebang とは何かと Linux でスクリプト用にどう使用されているかについて学ぶことができます。
- シェルビルトインとは何か、通常のシステムプログラムとどう違うのか;
- Bash変数の使い方と特殊変数とは;
- Bashコマンド置換の使い方。
- Bashでの簡単なIF文の使い方;
このように、かなり長いプログラムになっていますので、早速、Bashスクリプトの作成と実行方法を見ていきましょう。
Getting Started with Bash
コマンドを発行する前に、Bash とシェルの共通の歴史について簡単に説明します。
History of Bash
最初のバージョンの Bash シェルは Brian Fox によって 1989 年にリリースされ、Unix シェルのオープンソース実装として提供されています。
当時、Unix システムが生まれ始めたとき、そのシステムは Bourne シェルという標準の Unix シェルを使っていました。
初期の Unix では MIT や Bell Labs などで開発したシステムはフリーではなく、オープンソースでもなかったんです。
たとえそれらのツールにドキュメントが提供されていたとしても、(リチャード・ストールマンが率いる)GNUイニシアチブにとって、独自のバージョンのUnixシェルを持つことが優先事項となりました。
GNUプロジェクトを発表してから6年後、Bash (Bourne-Again Shell) シェルは、オリジナルの Bourne シェルよりもさらに機能を充実させたものとして生まれました。
- Bash はコマンドライン・インタプリタ、言い換えれば Unix シェルです。 ターミナルを開くときはいつでも、ほとんどの場合 Bash シェルである Unix シェルに直面することになります。
ターミナルで直接コマンドを入力すると、コマンドはシェルによって解釈され、システムコールを使用して実行されて戻り値がエンドユーザーに返されます。
現在使用しているインタープリターがわからない場合、SHELL 環境変数が現在使用しているシェルを示します。
$ printenv SHELL
このケースでは、おわかりのように、正しく Bash コマンド インタープリターを使って作業しています。
「Bash スクリプト」と「シェル スクリプト」のような用語が同じように使われていても、ディストリビューションによっては実際には同じものを説明していない場合があることに注意する必要があります。
Debian 10 などの最近のディストリビューションには、オリジナルの Bourne シェル (sh という名前) から独自のシェル実装 (この場合は Dash または Debian Almquist シェル) へのシンボリックリンクがある
- Bash もコマンドライン言語として記述しており、Bash 言語とも呼ばれています。 Bashは、パイピングや複数のコマンドを一度に実行するなどの基本的な機能を持つために使用できる演算子やオペランドのセットを公開しています。
基本的なパイピングを行う場合、「|」記号を使用することが多い。 この記号は Bash コマンドライン言語の一部です。
同じ論理が “&&” 記号にも当てはまり、最初のコマンドが成功した場合にのみ、2 番目のコマンドを実行します。
$ command1 && command2
Create and Run Bash Scripts
Bash シェルと Bash コマンドライン言語の背景がわかったところで、簡単な Bash スクリプトを作成して実行するところから始めましょう。
最初の Bash スクリプトを作成するには、単に「script.sh」という名前のファイルを作成します。
すでにお気づきかと思いますが、元の Bourne シェル (sh とも表記される) を参照して、まだ「sh」拡張子が使用されています。
$ touch script.sh
さて、拡張子 “sh” で終わるファイルを作成するだけでは、あなたのスクリプトがシェル スクリプトとみなされるには不十分です。
file コマンドを実行すると、あなたのファイルがまだシェル スクリプトとみなされないことが実際にわかります。
ファイルをシェル スクリプト ファイルとして記述するには、ファイルの先頭に shebang 行を指定する必要があります。
Specifying shell using shebang
長い間 Linux を使用している場合、ファイルの先頭に shebang 行があることに既に気づいている可能性が非常に高いと思います。
Shebang は “Hash + “Bang”” の略で、このスクリプトを解釈するためにどのシェルを使用するかを指定するために、シェルスクリプトの最初に設定するワンライナーである。
$ which bash/bin/bash
インタープリタへのパスを決定するために、”which” コマンドを使用することができます。
#!/bin/bash
ファイルの先頭にこの行を追加したので、違いを見るために “file” コマンドを再実行します。
ご覧のように、出力はわずかに異なっています。今回は、あなたのスクリプトが “Bourne-Again shell script” として、さらに実行形式として見られています。
では、スクリプトの先頭で shebang 行を指定しないとどうなるでしょうか。
shebang 行を指定しない場合、スクリプトは execute コマンドを開始するために使用した現在のシェルで実行されます。
Bash スクリプトの作成方法がわかったので、それを実行する方法を見ていきましょう。
Execute Bash Scripts
Linux で Bash スクリプトを実行するには、基本的に 2 つの方法があります:
- 使用するシェルインタプリタとスクリプトファイルを指定する。
bash スクリプトを実行するために、使用するインタープリターを自分で指定します。
$ bash <script>$ /bin/bash <script>
前に使用した例を使用すると、次のような出力になります。
ご覧のように、この方法ではファイルの実行権限さえ必要ではありません。
見てのとおり、実行権限なしで他のユーザーとしてログオンした場合、私はまだこのスクリプトを実行できます。
他のユーザーによるファイルの実行を防ぐために、(自分だけがアクセスできる)保護ディレクトリにスクリプトファイルを格納したい場合があるので、これは重要な発言と言えます。
スクリプトへのパスを指定する
bashスクリプトを実行する他の方法は、ファイルへのパスを指定することである。
この方法を使用するには、ファイルに実行パーミッションが必要である。
$ chmod u+x <script>
見てのとおり、ファイルの色はかなり異なっています。現在のターミナルでは、特定の色、この場合は緑色を使って実行ファイルをハイライトしています。
現在の作業ディレクトリにある “script.sh” というファイルを使用して、
$ ./script.sh
別のディレクトリにいる場合は、スクリプト ファイルへの絶対パスを指定する必要があります。
$ /home/user/script.sh
もうお気づきかと思いますが、この方法は、毎回スクリプトへのパスを指定しなければならない場合、あまり便利ではありません。
幸いにも、コマンドラインにファイル名を入力するだけで、スクリプトを実行する方法があります。
スクリプトを PATH に追加する
スクリプトをスクリプト ファイルと見なすには、拡張子 “.sh” は必要ありません。
簡単のために、既存の “script.
Linux でファイル名を変更するには、単に “mv” コマンドを使用して、ソースと宛先を指定します。
$ mv script.sh script
さて、もしあなたが “script” と入力してスクリプトを実行したかったらどうでしょうか?
そのためには、スクリプトへのパスをPATH環境変数に追加しなければならない。
PATH環境変数の現在の値を表示するには、「PATH」引数で「printenv」を使用する。
$ printenv PATH
現在の作業環境の PATH を更新するには、以下の構文で PATH 環境変数を編集します。
$ export PATH="<path_to_script>:$PATH"
これで、先ほど定義した “script” コマンドがパスを指定せずに直接使えるようになり、他のコマンドのように起動できるようになりました。
注意: もしこの変更を永久にしたい場合は、PATH 変数を適切に更新する手順に従ってください。
Shell built-ins explained
Script で変数を宣言する前に、シェル組み込み関数について知っておくことは重要なことです。
Bash シェルで作業しているとき、ほとんどの場合「プログラム」を実行しています。
プログラムの例としては、「ls」、「fdisk」、「mkdir」などがあります。 これらのコマンドのヘルプは “manual” の略である “man” コマンドで見つけることができます。
しかしながら、 “source” コマンドのドキュメントを読もうとしたことがありますか?
source コマンドはシェル組み込み関数なので “man” でドキュメントを読むことはできないでしょう。
$ help <command>
シェル組み込み関数のリストは非常に広範囲ですが、ここでは Ubuntu システムで見つけることができるすべての bash 組み込みコマンドのスクリーンショットを掲載します。
Bash 変数を使用する
Bash ビルトインについて理解したところで、いよいよ独自の Bash スクリプトを書き始める時がきました。
注意事項として、ターミナルで入力したコマンドは、まったく同じ方法で Bash スクリプトで使用できます。
たとえば、単に “ls -l” コマンドを実行するスクリプトが欲しい場合、単にスクリプトを編集して shebang 行とコマンドを追加します。
#!/bin/bash# This simple script executes the ls commandls -l
さて、もしあなたが Bash 変数にしたいのならどうしますか?
Bash 変数は、さまざまな入力を保存できるシンプルなプログラム変数です。
Bash 変数を宣言するには、変数名とその値を等号で区切って指定するだけです。
VAR=value
Bash 変数の内容をスクリプトで使用できるようにするには、「$」を使って変数名を追加してください。
echo $VAR
変数の値を持つためにこの構文を使用できる場合でも、「ブラケット」表記を使用できます。
echo ${VAR}
この構文を使用すると、変数は一緒に組み合わせることが可能です。
たとえば、VAR1 と VAR2 という名前の 2 つの Bash 変数がある場合、次の構文を使用してそれら両方を表示させることができます。
コマンド置換は、コマンドの結果を変数に格納するために Bash シェルで使用されるテクニックです。
Bash でコマンドを置換するには、ドル記号を使用し、コマンドを大括弧で囲んでください。
VAR=$(command)
たとえば、カレントディレクトリのファイル数の結果を得るには、
#!/bin/bashNUMBER=$(ls -l | wc -l)echo "${NUMBER} files in this directory!"
このように、コマンド置換はシェルスクリプトで動的にコマンドを実行してユーザーに値を返すのに使用できるため非常に便利である。
エンドユーザーに結果を返すといえば、正しく終了しないスクリプトをどのように扱うのでしょうか。
スクリプト内のコマンドが正しく実行されなかった場合はどうすればよいですか。
Understanding Exit Statuses
スクリプトを実行しているとき、たとえ値を返していなくても、スクリプトは常に「終了ステータス」と呼ぶものを返す。
Bash スクリプトにおける終了ステータスは、スクリプト実行が成功したかどうかを示します。
ステータスコードがゼロであればスクリプト実行は成功したことになります。
終了ステータスを示すには、bash シェルで任意の有効なコマンドを実行します。
echo "This is a simple working command"
では、最後に実行したコマンドの終了ステータスを調べるためにこのコマンドを使用します。
echo ${?}
ご覧のように、このコマンドの出力は “0” または最後に実行したコマンドの終了ステータスになります。
この構文 (“${?}”) は、コマンドが正しく実行されたことを確認するためにスクリプトで使用できます。
終了ステータスは、特定のステータス コードでスクリプトを終了するためにスクリプトで使用できます。
たとえば、エラーでスクリプトを終了したい場合、スクリプトで次のコマンドを使用できます。
exit 1
同様に、スクリプトが正常に実行されたことを指定するために、「ゼロ」終了コードを使用することができます。
exit 0
ステータス コードが正しいかどうかを確認するには、IF 文などの基本的な条件文が必要になります。
Bash で条件を操作する
場合によっては、bash スクリプトの実行は複数のコマンドを隣り合わせにするだけではなく、条件付きのアクションが必要なことがあります。
場合によっては、現在のユーザーがルート ユーザー (またはシステム上の特定のユーザー) であるかどうかをチェックする条件を設定すると便利なことがあります。
“if” はシェル組み込みで、結果としてマニュアルは “help” コマンドで入手できます
$ help if
ヘルプページではセミコロンを使って if コマンドの構文を説明していますが、ここではこの構文(同等となるもの)で行きます
if ]then <commands>else <command>fi
Practice case : ユーザーが root であるかどうかを確認する
if 文がどのように使用できるかを紹介するために、あるユーザーが root ユーザーであるかどうかを確認する簡単なスクリプトを作成することにする。
注意事項として、どの Unix システムでもルートユーザーは常に UID がゼロに設定されている。
この情報を知った上で、UID がゼロに設定されているかどうかをチェックし、もしそうであればスクリプトの残りを実行し、そうでなければスクリプトを終了させる。
他のチュートリアル(ユーザー管理について)で説明したように、「id」コマンドを使用すると現在のユーザーIDを取得できます。
$ id -u1000
このコマンドを使用して、スクリプトを実行するユーザーがルートかどうかをチェックします。
新しいスクリプトを作成し、shebang行を追加します。
#!/bin/bash
そのすぐ下に、「id」コマンドを追加し、コマンド置換を使って「USERID」という変数に結果を格納します。
USERID=$(id -u)
USERID に現在のユーザー ID が格納されたので、IF 文を使用してユーザー ID が 0 かどうかをチェックします。
if ]then echo "This is root"else exit 1fi
ここで、現在のユーザーとしてスクリプトを実行すると、スクリプトは単に終了ステータス 1 で終了します。
では、ルート ユーザーとして (sudo コマンドで) スクリプトを実行してみます。
ご覧のように、情報メッセージが表示されて、エラー コード 0 でスクリプトが終了しています。
結論
このチュートリアルでは、Bash プログラミング言語と、システムで Bash スクリプトを作成するための使用方法について学習しました。
Bash についてより多くの知識を得たので、ニーズに合わせて独自のスクリプトを書くことから始めてください: たとえば、アーカイブのバックアップファイルを作成するチュートリアルから始めることができます。