目次
シュルスクリプトの基本的な機能
基本的なシェルスクリプトの書き方は過去記事を参照。
wantanblog.hatenablog.com
もう少し実用的なスクリプトがかけるようにいくつかの機能を学習する。
シェルスクリプトで変数を使う
変数は特に宣言なくつくればよいみたい。
変数に値を格納するときは「=」の前後にスペース等はつけないこと。
test=/home/wantan
変数の値を取り出すときは「$」を先頭につければよい。
ls $test
前記事で作成したシェルスクリプト(以下、「sample.sh」)で変数を使用してみる。
正常に実行しなおせたらOK!
たらたらしたパスを書かなくてよいから見た目もすっきりした。
#!/bin/bash # 変数にログファイルのパスを設定する logfile=/home/wantan/work/sampleDir/shell.log cd / #ルートディレクトリに移動 ls -l > $logfile #実行結果をログファイルに書き出す cd /home/wantan/work/sampleDir/ #作業ディレクトリに移動 ls -l >> $logfile #実行結果をログファイルに追記
コマンド結果を文字列として扱う
ログファイルの名前に実行日を付与したかったりする。
日付は「date」コマンドで取得できるがそのままだとうまく変数などに格納できない
まずはdateコマンドの確認。好きな形式で出力できることを確認する(ここでは"yyyy/mm/dd")。
date +%Y/%m/%d
これをそのままシェルスクリプト上の変数に以下のようにぶっこもうとする。
# 変数に日付を格納する dateX=date +%Y%m%d
すると以下のようにエラーになるはず
./sample.sh: 行 4: +%Y%m%d: コマンドが見つかりません
本題。これを回避するためにコマンド置換を使用する。
「$( )」でコマンドをくくる。
# 変数に日付を格納する dateX=$(date +%Y%m%d)
件の「sample.sh」にコマンド置換を活用してみる
#!/bin/bash # 変数に日付を格納する dateX=$(date +%Y%m%d) # 変数にログファイルのパスを格納する logfile=/home/wantan/work/sampleDir/shell_$dateX.log cd / #ルートディレクトリに移動 ls -l > $logfile #実行結果をログファイルに書き出す cd /home/wantan/work/sampleDir/ #作業ディレクトリに移動 ls -l >> $logfile #実行結果をログファイルに追記する
以下のようにログファイルに本日日付が付与できる。
-rw-rw-r--. 1 wantan wantan 2864 6月 17 23:22 shell_20190617.log
コマンドラインからスクリプトに入力をする
作成したシェルスクリプトに対して変数の値や入力値を変えたい場合がある。
そのような場合はコマンドラインからの入力をスクリプト内で受け取るようにする。
「$1」とするとコマンドラインからの入力をスクリプト内で受け取るようになる。
以下、「command.sh」について
#!/bin/bash test="command is => "$1 echo $test;
複数の入力を行いたい場合は「$2」、「$3」とすると2個3個と入力することができる。
条件に応じて処理の流れを変える[if分]
シェルスクリプトでも他のプログラミング言語と同様にもちろん条件分岐を行うためのif分が存在する。
この辺りまで使いこなせるようになるとだいぶ実践的なスクリプトが記述できるようになる。気がする。。
先ほどの「command.sh」に条件分岐を追加してみる。
#!/bin/bash test="command is => "$1 # 入力値$1が空だった場合 if [[ $1 = "" ]] then # 変数testを上書きする。 test="空はダメです!入力をしてください(-_-メ)" fi echo $test;
形式は必ず覚えていなければならない。形式的に「_」(アンダーバー)は半角スペースを表す。
if _ [_【条件文】_] #ここで必ず改行
then
【処理】
fi #if文の終了
「command.sh」は「$1」をそのまま読み取ろうとすると空だった場合に警告が発生するので警告を防ぐために二重カッコのような
” ”のように記述してある。
実行結果は以下の通り。
入力がある場合は修正前と結果は変わらず、入力がない場合は入力を促すメッセージが表示されるようになった!!
なお、条件に一致しない場合の処理を記述したい場合は「else」で記述すればいい。
#!/bin/bash test="command is => "$1 # 入力値$1が空だった場合 if [[ $1 = "" ]] then # 変数testを上書きする。 test="空はダメです!入力をしてください(-_-メ)" else test=$test"(else文あり)" fi echo $test;
エラーに対応する
条件分岐を知ったので、ついでにエラーに対応する方法も記述しておく。
以下、「error.sh」について
#!/bin/bash test=$1 ls -l $test
上記のスクリプトでは入力引数がディレクトリの場合は正常に処理が行われるが、それ以外の場合はエラーが表示されるはずである。
これに対応する。
入力値がディレクトリかどうかで判断する方法もあるが、ここでは幅広く対応するために処理結果を見て以降の処理を行わないという対応方法にする。
#!/bin/bash test=$1 ls -l $test if [ $? != 0 ] then echo "処理に異常が発生しました。処理を中断します。" exit #異常が発生した場合ここで処理を中断する。 fi echo "処理が正常終了しました。"
「$? 」で直前の処理結果を取得する。
コマンドの処理結果は正常終了した場合「0」となるため、0以外の場合は中断処理を加える。
以下、処理結果。
上が異常終了した場合、下が正常終了した場合。
処理をループさせる
条件分岐ときたら次はループ処理でしょう(?)
ということでシェルスクリプトでのループ処理について
ループ処理では以下のようにfor do doneを使用する。
for name in file.txt file1.txt do echo $name done
またループ対象となる「in」の後ろには「ls」コマンド等の実行結果を入力することもできる。
こっちのほうが実践的かもしれない。
for name in ”ls” do echo $name done
またひとつスクリプトを作成してみる。
今回は「シェルスクリプトで変数を使う」である。作成した「sample.sh」にさらに編集を加えて、
ディレクトリに対してlsコマンドを実行する「error.sh」を呼び出す。
#!/bin/bash # 変数に日付を格納する dateX=$(date +%Y%m%d) # 変数にログファイルのパスを格納する logfile=/home/wantan/work/sampleDir/shell_$dateX.log echo "実行結果を記入する。" > $logfile #ディレクトリを一覧で取得する。 for direname in $(ls -d */) do # ディレクトリごとにerror.shを実行する ./error.sh $direname >> $logfile done
処理の流れは以下の通り。
①ログファイルを生成する。
②先頭行に記述する。
③ディレクトリごとにループ処理を開始する
④ループ処理の中で「error.sh」を実行する。
⑤実行結果をログファイルに追記する。
実行結果は以下の通り。
ログファイルの中身を確認する。
できてた!!
ここまでで、だいぶ実践的なスクリプトが組めるようになったはずである。
Linuxの本を使った学習はいったんここで一区切りとしたい。
また新しく本を買うか必要になったら記事を追加していきます。
参考書は取り上げていない部分もありますが「シス菅系女子①」でした。