シェルスクリプトを書く上で、よく忘れるのでメモ
動作はCentOS5 or RHEL5+Bash(Bourne-Again Shell)で確認。
○行説明(わかりづらかったので色付け)
スクリプト例
実行結果
$ sh -n test.sh
シェルスクリプトのトレース
-xのオプションを付けてシェルスクリプトを実行
例:
○ test.sh(中身)
export LANG=C
echo "test"
echo `date`
○ シェルスクリプト実行結果
$ sh -x test.sh
+ export LANG=C
+ LANG=C
+ echo test
test
++ date
+ echo Sat Jan 1 00:00:00 JST 2000
Sat Jan 1 00:00:00 JST 2000
※ export LANG=Cをしてるのは、ターミナル上で文字化けの回避
因みに、毎回トレースを入れるなら、マジックナンバー部分に
#!/bin/sh -x
としておけば普通に起動してもトレースモードになる。
$#
例:
○test.sh (中身)
#!/bin/sh
echo $#
○結果(1)
$ sh test.sh 0
1
○結果(2)
$ sh test.sh 0 1
2
if 条件
then
コマンド
elif 条件
then
コマンド
else
コマンド
fi
例:入力されたパラメータの入力値調査
val=$1
if [ ${val} -lt 1 ]
then
echo "入力値は1より小さい"
elif [ ${val} -eq 1 ]
then
echo "入力値は1"
else
echo "入力値は1より大きい"
fi
もちろん、elif 条件ぬきでも書くことはできる。
数値比較
演算子 | 意味 |
---|---|
-eq | == equal 同じ |
-ne | != not equal 違う |
-lt | < less than 未満(より小さい) |
-gt | > greater than より大きい |
-le | <= less equal than 以下 |
-ge | >= greater equal than 以上 |
英語で覚えるとわかりやすい。
文字列比較
演算子 | 意味 |
---|---|
= | 等しい |
!= | 等しくない |
(何故か先日ここでひっかかったので追加w)
例:文字列が等しいか
if [ ${str} = "test" ]
then
echo "ok"
else
echo "ng"
fi
ファイル属性
演算子 | 意味 |
---|---|
-d | ディレクトリなら真を返す |
-f | 通常ファイルなら真を返す |
-L | シンボリックリンクなら真を返す |
-r | 読み取り可能ファイルなら真を返す |
-w | 書き込み可能ファイルなら真を返す |
-x | 実行可能ファイルなら真を返す |
-s | サイズが0より大きければ真を返す |
例:カレントディレクトリ上に「test」ディレクトリが有るか
if [ -d test ]
then
echo "ok"
else
echo "ng"
fi
※否定の場合は!を付ける
if [ ! -d test ]
then
echo "ok"
else
echo "ng"
fi
$?
例:test.shというプログラムを走らせた結果で分岐
./test.sh
if [ $? -eq 0 ]
then
exit "ok"
else
exit "ng"
fi
$!
例:a.shというプログラムをバックグラウンドで走らせてa.shのPIDを取得
./a.sh > /dev/null 2>&1 &
val=$!
echo ${val}
$$
シングル?ダブル?それともバッククォート?
もち理解していますが、書いておきます
上にも出てきていますが、関数dateをechoして結果を変数に保存したりするとき、そのまま打つと
# echo date
date
そのまま出ちゃいます
では順にシングル、ダブル、バックとやってみましょう
○シングルクォート
# echo 'date'
date
○ダブルクォート
# echo "date"
date
○バッククォート
# echo `date`
Sat Jan 1 00:00:00 JST 2000
バッククォートの時が意図した処理になってあとは普通にdateという文字列表示です。
では次に、シングルとダブルの違い
変数に入れるのが面倒なのでLANG使わせてもらいましょう
○シングルクォート
# echo '${LANG}'
${LANG}
○ダブルクォート
# echo "${LANG}"
ja_JP.UTF-8
シングルの方は$変数を無視して表示です
ここを使い分けられるようになるとシェルスクリプトの幅が広がるので覚えちゃいましょう~
※${LANG}と記載していますが、$LANGでもいいです。
(プチ実用(?)シェルスクリプトのサンプル)
※いかなる責任も負えませんので、使用は自己責任でお願いします。
※ダウンロード用サンプルスクリプトはUTF-8 LFで作成しています。
デーモン動作チェックスクリプト
再起動直後ぐらいに実行すると良さそうなシェルスクリプト
例: デーモン動作チェックプログラム
原理は単純pidファイルを開いて、そのプロセスが生きているかどうか確認するだけ。
○proc_chk.sh (DL準備中。コピペしてくださいw)
※2010/06/22 更新
#!/bin/sh
function proc_chk()
{
RES=0
chk_str=$1
if [ -f $2 ]
then
pid_file=`cat $2|sed s/' '//g`
if [ -d /proc/${pid_file} ]
then
RES=1
else
RES=0
fi
else
RES=0
fi
printStr=${chk_str}'########################'
STR_BUF=`echo ${printStr} | awk '{printf("%-20.20s",$1);}'|sed s/#/./g`
if [ ${RES} -eq 1 ]
then
echo "${STR_BUF}[ OK ]"
else
echo "${STR_BUF}[ NG ]"
fi
}
########################
#ここから下に調べたい物を記載。
# proc_chk デーモン名(何でもいい) PIDファイル
#Apache check
proc_chk Apache "/var/run/httpd.pid"
#ntpd
proc_chk ntpd "/var/run/ntpd.pid"
#sshd
proc_chk sshd "/var/run/sshd.pid"
○結果
# ./check_proc.sh
Apache..............[ NG ]
ntpd................[ OK ]
sshd................[ OK ]
※Apacheが落ちている例
個人的メモでは、awkの桁合わせ部分が覚えられないためのメモw
プロポーショナルフォントだからずれて見えるけど、等幅フォントなら問題無し
拡張子一括変換スクリプト
○ext_chg.sh (DL準備中。コピペしてくださいw)
#!/bin/sh
#変更前拡張子
ext=".TXT"
#変更後拡張子
chext=".txt"
list=`ls`
for file in ${list}
do
chfile=`echo ${file}|sed "s/${ext}/${chext}/g"`
if [ ${file} != ${chfile} ]
then
mv ${file} ${chfile}
fi
done
簡易CPU負荷チェックスクリプト
○loadaverage_chk.sh (DL準備中。コピペしてくださいw)
※現状では変数:min1のみ使用。min5とmin15は使っていません。
※crontabを使用してスクリプトを呼び出すと、定期監視になります。
※負荷が閾値を超えた場合メールがガンガン届くので注意してください。
#!/bin/sh
#-------------------------------------------------------------------------------------------------#
#閾値
threshold=1
#宛先
toaddr=root@localhost
#送信元
fromaddr=alertmail@localhost
#-------------------------------------------------------------------------------------------------#
loadaverage=`uptime | awk '{print $8 $9 $10;}' | tr "," " "`
min1=`echo ${loadaverage} | cut -d" " -f1`
min5=`echo ${loadaverage} | cut -d" " -f2`
min15=`echo ${loadaverage} | cut -d" " -f3`
comp=`echo "scale=2; ${threshold} < ${min1}" | bc`
if [ ${comp} -eq 1 ]
then
mainmsg="サーバの負荷が閾値${threshold}を超え、${min1}になりました。"
echo "${mainmsg}"
echo "${mainmsg}" | /bin/mail -s "loadaverage alert" ${toaddr} -- -f ${fromaddr}
fi
ftp通信スクリプト
○ftp_cron.sh (DL準備中。コピペしてくださいw)
※ざっくりと完成(2010/12/17 現在)
時々"ftp -n"と言うプロセスが残ったままになるようなのでpidを吐いてkillするようにしたものです
#!/bin/sh
# initialize ------------------------------------------
HOST_NAME="192.168.127.51"
FTP_PID_PATH="./ftppid/"
FTP_PID_FILE_NAME="ftp_`date +%Y%m%d%H%M%S`.pid"
KILL_DAY=1
# -----------------------------------------------------
#PID DIR CHECK
if [ ! -d ${FTP_PID_PATH} ]
then
mkdir ${FTP_PID_PATH}
fi
#FTP Connect
ftp -n ${HOST_NAME} < ftpconnect.txt &
#Write PID
echo $! > "${FTP_PID_PATH}${FTP_PID_FILE_NAME}"
#Delete PID file
FIND_FILE=`find ${FTP_PID_PATH} -type f -print`
for pidfile in ${FIND_FILE}
do
pid_res=`cat ${pidfile}`
ps_res=`ps aux | grep ${pid_res} | grep ftp | grep -v grep | wc -l`
if [ ${ps_res} -eq 0 ]
then
rm -f ${pidfile}
fi
done
#Kill deadprocess
FIND_FILE=`find ${FTP_PID_PATH} -type f -mtime +${KILL_DAY} -print`
for pidfile in ${FIND_FILE}
do
kill `cat ${pidfile}`
rm -f ${pidfile}
done
user test password
bin
lcd /var/www/html/
cd /ftproot/
get test.txt
bye
※補足
接続ユーザ:test 、 パスワード:password で接続
毎回PIDを吐いて2日前のプロセスをkill。プロセスチェックで実態の無いPIDファイルは削除