12.2 シェルスクリプトの基本
Linux Essentials Online Text | 2021/07/29

シェルスクリプトはシェルプログラム上で実行できるスクリプト言語の1つです。スクリプト(script)は「台本」という意味で、コンピュータに実行させたい処理を記述してその台本通りに動かすことが可能です。

今まではコマンドを1行づつ入力し、その結果を得て次のコマンドを入力する、という行為を繰り返してきました。しかしながらシェルスクリプトを用いると、今までユーザがシェルに対して1行づつ入力していたコマンドを、自動的に連続して実行させることができます。

シェルスクリプトは、学習したコマンドを条件分岐や繰り返しなど制御機能を加え実行することができます。また、ただコマンドを並べるわけではなく、特定の条件での実行など体系的に制御ができます。これをシェルスクリプトプログラミングといいます。

シェルスクリプトの作成

それでは実際にシェルスクリプトを作成してみましょう。ここではシェルスクリプトを作成し、実行する手順を紹介します。

なお、この章ではroot権限は必要ありません。rootユーザで誤った設定を行い、実行してしまうとシステムに悪影響を与える可能性がありますので、一般ユーザで実行しましょう。

シェルスクリプトはテキストで記述します。vi等のテキストエディタを利用すれば問題有りません。まずは、script.shというシェルスクリプトを記述してみましょう。

$ vi pwddate.sh

テキストの内容は、下記のように入力します。
2行目は空行で構いません。入力したら、保存して終了してください。入力が終わったら、保存します。

#!/bin/bash

date >> research.log
uptime >> research.log
free >> research.log

シェルの指定

1行目に#!/bin/bash と記述しました。この「#!」で始まる行の事をShebang(シェバン)といいます。

その次に「/bin/bash」を指定しています。ここには利用するシェルの種類とそのコマンド位置を記述します。Bシェル(bash)で実行しますよ。という宣言です。これをインタプリタといいます。

今回はbashを利用するためにこのように記載しますが、別のシェルを使用する場合はそのシェルを指定するパスを記載します。1行目で指定されたシェルを元に3行目以降を実行しますので、2行目は必ず空行にします。

スクリプトの内容

今回は、3行のコマンドを実行するように作成しています。

dateコマンドは、実行時のシステムの日時を取得するコマンド、uptimeコマンドは、実行時のシステムの負荷状況を取得するコマンド、freeコマンドは、実行時のシステムのメモリ使用率を取得するコマンドです。これらのコマンドを実行するたびに「research.log」というファイルに追記リダイレクトする、という処理が行われます。

これらのコマンドは、それぞれ単独で手動実行することができますが、これらをシェルスクリプトにすることによって、1度に実行することができるようになります。なお、処理は上から順番に実行されます。

パーミッションの変更

次にscript.sh を実行できるようにパーミッションを変更します。作成したファイルには実行権限がありませんので、script.shに実行権限を付与します。

$ ls -l script.sh
--rw-r—r-- 1 lpic-user lpic-user 21 Jun 6 09:51 script.sh
$ chmod a+x script.sh
$ ls -l script.sh
--rwxr-xr-x 1 lpic-user lpic-user 21 Jun 6 09:51 script.sh

それでは実行してみましょう。
シェルスクリプトの実行方法は複数あります。下記、どの方法でも実行することができます。

$ bash script.sh
$ sh script.sh
$ ./script.sh
$ source script.sh

なお、sourceコマンドは、他のコマンドの実行方法と異なり、現在のシェルで実行することができます。

実行すると、スクリプトに記載した処理通り「research.log」というファイルが生成されます。
ファイルの中身に、指定した情報が含まれていることを確認してみてください。

$ ls -l research.log
-rw-rw-r--. 1 lpic-user lpic-user 316  7月 29 01:11 research.log
$ cat research.log
2021年  7月 29日 木曜日 01:11:39 JST
 01:11:39 up 2 days, 16:17,  1 user,  load average: 0.00, 0.01, 0.05
            total       used      free      shared   buff/cache   available
Mem:     1014756     170276     655224       51272       189256      652728
Swap:     839676      0    839676

シェルスクリプトの基礎知識

シェルスクリプトを書くときに、いくつか必要な知識があります。

コメント

コメントとはプログラム上に書く注釈のことです。プログラム上では何ら意味を持ちませんが、プログラムを書く人間が目安にすることがあります。例えば、複数名が1つのファイルを管理する場合等、追記した日時や理由などが記載されていることで、対応内容や変更理由などを確認することができ、非常に有効な記述となります。

コメントは「#(シャープ)」で始めた行がコメント行となり、その行はプログラム的に無視されます。「コメントする」とか「コメントアウトする」という表現をします。

例えば、以下のように記載されている場合2行目の「# insert….」の行は無視されるため、実行上は何ら影響がありません。なお、1行目の「#!/bin/bash」は、特殊な記載でコメントされているわけではありません。

#!/bin/bash
# insert xyz into value abc and output it
abc=xyc
echo $abc

また、「#(シャープ)」は特定のコマンドやパラメータを無効にしたい場合に使用するケースもあります。

引数

シェルスクリプトでは、実行時に引数を設定するとその値を参照することができます。

<実習: 引数出力の確認>

次のようにargs.shを作成してみましょう。

$ vi args.sh

スクリプトの中身は、下記のように入力してみてください。

#!/bin/sh

echo '$1:' $1;
echo '$2:' $2;
echo '$3:' $3;
echo '$10:' $10;
echo '${10}:' ${10};
echo '$0:' $0;
echo '$#:' $#;

作成したシェルスクリプトを、以下のように実行します。

$ chmod +x args.sh
$ sh args.sh aa bb cc dd ee ff gg hh ii jj
$1: aa
$2: bb
$3: cc
$10: aa0
${10}: jj
$0: args.sh
$#: 10

2行目が、実際の実行コマンドです。
今までのシェルスクリプトの実行とは異なり引数を指定しています。引数は、実行するシェルのファイル名を入力した後、スペースで区切って指定します。複数指定する場合は、上記のようにスペースで区切って羅列していきます。今回は、aa~jjまでの10個の引数を指定しています。

3行目以降が実行結果ですが、それぞれ以下のような意味を持っています。
$1:1つ目の引数を表示します。つまり「aa」です。
$2:2つ目の引数を表示します。つまり「bb」です。
$3:3つ目の引数を表示します。つまり「cc」です。
$10:10個目の引数、ではなく、1つ目の引数($1)と0を表示します。つまり「aa0」です。
${10}:10個目の引数を表示します。つまり「jj」です。
$0:実行したスクリプトファイルを表示します。つまり「args.sh」です。
$#:指定した引数の合計値を表示します。今回は10個していしたので「10」です。

引数を表示したい場合で、2桁以上の引数を表示する時は{}で括る必要がある点に注意しましょう。

シェルスクリプトにおける特殊変数

今回シェルスクリプトの中に記載した「$+数字」で記載された文字列は特殊変数です。これら特殊変数は、シェルスクリプトに与えられた引数を取得したり、スクリプト自体の情報にもとづき動作するために利用されます。

使える特殊変数には以下のようなものがあります。

<特殊変数一覧>

変数説明
$#引数の個数
$0実行したシェルのファイル名
$nn番目の引数。10以上になるときは{}で括る。
$$現在のシェルのプロセス番号
$?直前に実行したシェルの終了ステータス
$!直前に実行したシェルのPID

エスケープ

プログラミングには特別な文字があります。例えば、echoコマンドを利用する場合を考えてみましょう。echoコマンドで「”(ダブルクオート)」を出力する場合、次のような出力が考えられます。

 $ echo """

これは「”(ダブルクオート)」を「”(ダブルクオート)」で括ったもの、というつもりで記述していますが、実際にシステムがこのコマンドを解釈した場合は、最初の2つの「”(ダブルクオート)」で1組と解釈し、3つめの「”(ダブルクオート)」は閉じられていない状態、と認識してしまいます。

そのため、今回のケースでは「2つめの「”(ダブルクオート)」は区切り文字のダブルクオートではなく、文字として出力する」ということを伝えたいわけです。

この様な場合は「\(バックスラッシュ)」という特殊記号を用います。 「\(バックスラッシュ)」 を使用するとこの直後の1文字はただの文字(特殊効果を発揮しない文字)として処理することができます。このように、特殊な文字を文字列として認識させることを「エスケープする」といいます。日本語キーボードでは円マークが表示されますが、英字フォントなどを使うと「\」が表示されます。

<実習:エスケープシーケンスの確認>

$echo "\""
"	

「\(バックスラッシュ)」を該当文字の前に入力することで、この後に続く1文字だけを単なる文字として表現することができます。

改行

「\(バックスラッシュ)」はエスケープ以外の使い方として、一行が長くなる場合「\(バックスラッシュ)」を行末に付与することで、途中で折り返す機能も持っています。

$ echo "abcedfghijklmnopqrstuvwxyz"
abcedfghijklmnopqrstuvwxyz
$ echo "abcedfghijklmn\
> pqrstuvwxyz"
abcedfghijklmnpqrstuvwxyz

「$ echo “abcedfghijklmn」の後に「\」を入力して[Enter]キーを押下すると改行されますが、コマンドの入力は終了しません。残りの「pqrstuvwxyz”」を入力して[Enter]キーを押下することで、コマンドが全て入力されたことになり、結果、改行前と改行後の内容がつながって表示されています。

バックスラッシュによる改行は、シェルスクリト内でも使うことができます。

sourceコマンド

通常、シェルスクリプトを実行すると別のシェルで実行されますが、sourceコマンドはファイルに書かれたコマンドを“現在のシェルで実行する”というコマンドです。そのため、関数を設定するようなシェルを実行するときなどに使います。

書式:

source ファイル    

sourceコマンド以外に、「.(ドット)」を利用しても同等の機能を実現することも可能です。

PAGE TOP