- 1 はじめに
- 2 検証環境
- 3 Hello World
- 4 引数の使い方
- 5 if文の使い方
- 6 for文の使い方
- 7 while文の使い方
- 8 ファイルを読み込む方法(source)
- 9 ファイル、ディレクトリの存在有無を調べる方法
- 10 関数の使い方
- 11 配列の使い方
- 12 連想配列の使い方
- 13 シグナルを受信する方法(trap)
- 13 デバッグ方法
- Z 参考情報
1 はじめに
bsahのサンプルスクリプトです。
なお、bash変数展開については、bash変数展開の使い方 - hana_shinのLinux技術ブログを参照ください。
マニュアルは以下のページを参照しました。
Bash Reference Manual
2 検証環境
CentOS版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 3.10.0-1160.el7.x86_64
bashの版数は以下のとおりです。
[root@server ~]# bash --version GNU bash, バージョン 4.2.46(2)-release (x86_64-redhat-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. -snip-
3 Hello World
"Hello World"を出力するスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash echo "Hello World"
パーミッションを設定します。
[root@server ~]# chmod 700 tp.sh
スクリプトを実行します。
[root@server ~]# ./tp.sh Hello World
4 引数の使い方
実行するスクリプトに引数を指定することができます。引数の意味は、次のとおりです。
- $0:スクリプトのファイル名そのものを表す
- $1,$2,$3...:引数を表す
サンプルスクリプトを以下に示します。
[root@server ~]# cat tp.sh #!/usr/bin/bash echo "$0" "$1" "$2"
スクリプトを実行します。スクリプトのファイル名とスクリプトに指定した引数が出力されていることがわかります。
[root@server ~]# ./tp.sh aa bb ./tp.sh aa bb
5 if文の使い方
スクリプトを作成します。
5.1 if~fi
[root@server ~]# cat tp.sh #!/usr/bin/bash if [ "$1" -eq 1 ]; then echo 'one' fi
スクリプトを実行します。
[root@server ~]# ./tp.sh 1 one [root@server ~]# ./tp.sh 2 [root@server ~]#
5.2 if~else~fi
[root@server ~]# cat tp.sh #!/usr/bin/bash if [ "$1" -eq 1 ]; then echo 'one' else echo 'other' fi
スクリプトを実行します。
[root@server ~]# ./tp.sh 1 one [root@server ~]# ./tp.sh 2 other
5.3 if~elif~else~fi
[root@server ~]# cat tp.sh #!/usr/bin/bash if [ "$1" -eq 1 ]; then echo 'one' elif [ "$1" -eq 2 ]; then echo 'two' else echo 'other' fi
スクリプトを実行します。
[root@server ~]# ./tp.sh 1 one [root@server ~]# ./tp.sh 2 two [root@server ~]# ./tp.sh 3 other
6 for文の使い方
for文は以下のように使います。ここでは、リストにはブレース展開を使ってみます。
for 変数 in リスト do 処理 done
6.1 リストを使った繰り返し
echoを3回実行するスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash for i in {1..3} do echo $i done
スクリプトを実行します。
[root@server ~]# ./tp.sh 1 2 3
7 while文の使い方
7.1 無限ループする方法
無限ループするスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash while : do echo "Hello World" sleep 3 done
スクリプトを実行します。Ctrl+Cを押下してスクリプトの実行を終了します。
[root@server ~]# ./tp.sh Hello World Hello World Hello World ^C
8 ファイルを読み込む方法(source)
tp.shから関数addを定義したfunctions.shを読み込むスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash source ./functions.sh add 1 2 echo "Ans:"$?
[root@server ~]# cat functions.sh #!/usr/bin/bash function add() { a=$(($1+$2)) return $a }
スクリプトを実行します。
[root@server ~]# ./tp.sh Ans:3
9 ファイル、ディレクトリの存在有無を調べる方法
9.1 ファイルの存在有無を調べる方法(-f)
スクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash echo "$1" if [ -f "$1" ]; then echo 'exist' else echo 'not exist' fi
スクリプトを実行します。/tmp/hogeが存在するので、"exist"が出力されます。
[root@server ~]# touch /tmp/hoge [root@server ~]# ./tp.sh /tmp/hoge /tmp/hoge exist
スクリプトを実行します。/tmp/hogeが存在しないので、"not exist"が出力されます。
[root@server ~]# rm -f /tmp/hoge [root@server ~]# ./tp.sh /tmp/hoge /tmp/hoge not exist
9.2 ディレクトリの存在有無を調べる方法(-d)
スクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash echo "$1" if [ -d "$1" ]; then echo 'exist' else echo 'not exist' fi
スクリプトを実行します。/tmp/hogeが存在するので、"exist"が出力されます。
[root@server ~]# mkdir /tmp/hoge [root@server ~]# ./tp.sh /tmp/hoge/ /tmp/hoge/ exist
スクリプトを実行します。/tmp/hogeが存在しないので、"not exist"が出力されます。
[root@server ~]# rm -fr /tmp/hoge [root@server ~]# ./tp.sh /tmp/hoge/ /tmp/hoge/ not exist
9.3 AND条件を複数指定する方法(-a)
ファイル全てが存在する場合はtrue、1つでも存在しないとfalseを表示するスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash if [ -f /tmp/test1.txt -a \ -f /tmp/test2.txt -a \ -f /tmp/test3.txt ]; then echo "true" else echo "false" fi
テスト用のファイルを作成します。
[root@server ~]# touch /tmp/test1.txt [root@server ~]# touch /tmp/test2.txt [root@server ~]# touch /tmp/test3.txt
スクリプトを実行します。
[root@server ~]# ./tp.sh true
テスト用に作成したファイルを削除します。
[root@server ~]# rm /tmp/test3.txt rm: 通常の空ファイル `/tmp/test3.txt' を削除しますか? y
スクリプトを実行します。
[root@server ~]# ./tp.sh false
9.4 OR条件を複数指定する方法(-o)
スクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash if [ -f /tmp/test1.txt -o \ -f /tmp/test2.txt -o \ -f /tmp/test3.txt ]; then echo "true" else echo "false" fi
ファイルを1つ(/tmp/test3.txt)だけ作成します。
[root@server ~]# touch /tmp/test3.txt
スクリプトを実行します。ファイルが1つ存在するので、trueと出力されることがわかります。
[root@server ~]# ./tp.sh true
ファイルを削除します。
[root@server ~]# rm -f /tmp/test3.txt
スクリプトを実行します。ファイルが3つとも存在しないので、falseと出力されることがわかります。
[root@server ~]# ./tp.sh false
10 関数の使い方
10.1 関数の呼び出し方法
sub1という名前の関数を呼び出すスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash function sub1() { echo "Hello World" } sub1
スクリプトを実行します。
[root@server ~]# ./tp.sh Hello World
10.2 関数への引数の渡し方
引数を2つとるsub1という関数を定義します。そして、関数sub1に引数xxxとyyyを指定して呼び出します。
[root@server ~]# cat tp.sh #!/usr/bin/bash function sub1() { echo "$1" "$2" } sub1 xxx yyy
スクリプトを実行します。
[root@server ~]# ./tp.sh xxx yyy
10.3 戻り値を取得する方法(数値編)
引数に+1をした値を戻り値として返す関数sub1を定義します。関数の呼び出し元は$?を実行することで、関数sub1の戻り値を取得することができます。
[root@server ~]# cat tp.sh #!/usr/bin/bash function sub1() { tmp=$(($1+1)) return "$tmp" } sub1 10 echo $?
関数sub1が戻り値として11を返していることがわかります。
[root@server ~]# ./tp.sh 11
10.4 戻り値を取得する方法(文字列編)
returnコマンドは、文字列を戻り値として返すことはできません。戻り値を使用する場合は、関数内で標準出力に戻り値を出力し、コマンド置換でその値を取得します。
[root@server ~]# cat tp.sh #!/usr/bin/bash function sub1() { echo "Hello World" } ret=$(sub1) echo $ret
スクリプトを実行します。
[root@server ~]# ./tp.sh Hello World
11 配列の使い方
配列は"変数名[添字]=値"でセットし、"${変数名[添字]}"で参照します。
11.1 配列への値の代入、参照方法
配列への値の代入、参照するスクリプトを作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash color[0]="red" echo ${color[0]}
スクリプトを実行します。
[root@server ~]# ./tp.sh red
11.2 for文で配列を参照する方法
"${配列名[@]}"とすることで、配列の全ての要素を参照することができます。
[root@server ~]# cat tp.sh #!/usr/bin/bash color[0]="red" color[1]="black" for tmp in ${color[@]} do echo $tmp done
スクリプトを実行します。
[root@server ~]# ./tp.sh red black
11.3 値まとめて配列に代入する方法
”配列名=(値 値 値…)"とすることで、値をまとめて配列に代入することができます。
[root@server ~]# cat tp.sh #!/usr/bin/bash color=(red black pink) for tmp in ${color[@]} do echo $tmp done
スクリプトを実行します。
[root@server ~]# ./tp.sh red black pink
11.4 配列に値を追加する方法
”配列名+=(値 値 値…)"とすることで、配列に値を追加することができます。
[root@server ~]# cat tp.sh #!/usr/bin/bash color=(red black pink) color+=(white green) for tmp in ${color[@]} do echo $tmp done
スクリプトを実行します。配列に追加したwhiteとgreenが出力されていることがわかります。
[root@server ~]# ./tp.sh red black pink white green
12 連想配列の使い方
連想配列は、"配列名[キー]=バリュー"として定義します。キーの部分には、文字列を指定することができます。
12.1 バリューを出力する方法
配列名がscore、キーに名前、バリューに得点を定義した連想配列を作成します。
[root@server ~]# cat tp.sh #!/usr/bin/bash declare -A score score["tanaka"]=60 score["kato"]=100 for val in ${score[@]} do echo $val done
スクリプトを実行します。
[root@server ~]# ./tp.sh 60 100
12.2 キーを出力する方法
キーの値を出力する場合、配列名の前に"!"を付けて、"for 変数名 in ${!配列名[@]}"で指定します。
[root@server ~]# cat tp.sh #!/usr/bin/bash declare -A score score["tanaka"]=60 score["kato"]=100 for key in ${!score[@]} do echo $key done
スクリプトを実行します。
[root@server ~]# ./tp.sh tanaka kato
13 シグナルを受信する方法(trap)
シグナルを受信したら、trapコマンドを実行するスクリプトを作成します。SIGTERM,SIGHUP を受信したら、echoコマンドでメッセージを出力します。SIGINTを受信した場合、メッセージを出力した後、exitコマンドを実行してスクリプトを終了します。
[root@server ~]# cat tp.sh #!/usr/bin/bash trap "echo SIGTERM signal received." TERM trap "echo SIGHUP signal received." HUP trap "echo 'SIGINT signal received.'; exit" INT while true do echo "Running..." sleep 5 done
スクリプトを実行します。
[root@server ~]# ./tp.sh Running...
もう1つターミナルを開いてpsコマンドを実行します。スクリプトのPIDを確認すると、PIDが11689であることがわかります。
[root@server ~]# ps -C tp.sh PID TTY TIME CMD 11689 pts/0 00:00:00 tp.sh
スクリプトに対してSIGTERM,SIGHUPシグナルを送信します。
[root@server ~]# kill -SIGTERM 11689 [root@server ~]# kill -SIGHUP 11689
SIGTERM,SIGHUPシグナルを受信するメッセージが出力されていることがわかります。Ctrl+cを押下するとスクリプトがSIGINTを受信します。そしてexitコマンドを実行してスクリプトを終了していることがわかります。
[root@server ~]# ./tp.sh Running... SIGTERM signal received. Running... Running... SIGHUP signal received. Running... ^CSIGINT signal received.
13 デバッグ方法
シェルスクリプトが正しく動作しない場合のデバッグ方法を説明します。
13.1 シェルスクリプトの構文チェック
shellcheckコマンドを使って、シェルスクリプトの構文を静的にチェックすることができます。shellcheckコマンドの使い方は、以下を参照してください。
ShellCheckコマンドの使い方 - hana_shinのLinux技術ブログ
13.2 トレースオプションを指定する方法(-x)
1行目に-xオプションを指定して、シェルスクリプトを実行しみます。
[root@server ~]# cat tp.sh #!/usr/bin/bash -x echo "$1" if [ -d "$1" ]; then echo 'exist' else echo 'not exist' fi
シェルスクリプトを実行します。実行したコマンドと実行結果が表示されていることがわかります。
[root@server ~]# ./tp.sh /tmp + echo /tmp /tmp + '[' -d /tmp ']' + echo exist exist
13.3 ソースコードも一緒に出力する方法(-v)
"-v"は、ソースコードを出力するオプションです。”-x”と一緒に使うことで、どのコードを実行したのかがわかります。
[root@server ~]# cat tp.sh #!/usr/bin/bash -xv echo "$1" if [ -d "$1" ]; then echo 'exist' else echo 'not exist' fi
シェルスクリプトを実行します。
[root@server ~]# ./tp.sh /tmp #!/usr/bin/bash -xv echo "$1" + echo /tmp /tmp if [ -d "$1" ]; then echo 'exist' else echo 'not exist' fi + '[' -d /tmp ']' + echo exist exist
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ