共通関数を外部ファイルに作成する
各シェルスクリプトで共通に使用したい関数を外部ファイルに作成しておくと便利です。外部ファイルの読込は、各シェル内で「 . ファイル名 」と記述すれば外部ファイルに記述した関数を使用できます。外部ファイルに「変数」を定義しても同様に使用できます。以下は関数のサンプルです。
sample.fnc
# --共通関数定義--
# ログ出力関数
LOG()
{
# ログ出力先
LOG_DIR=./
# 引数展開
FILENM=`basename $0`
MSG=$1
# 変数定義
LOG_DATE=`date '+%Y-%m-%d'`
LOG_TIME=`date '+%H:%M:%S'`
LOGFILE="${LOG_DIR}${LOG_DATE}_`basename $0 .sh`.log"
# ログ出力実行
printf "%-10s %-8s %-14s %-50s\n" \
"${LOG_DATE}" "${LOG_TIME}" "${FILENM}" "${MSG}" >>${LOGFILE}
}
# 年月取得関数
GetYM()
{
SYSTEM_MONTH=`date '+%Y%m'`
echo ${SYSTEM_MONTH}
}
# 年月日取得関数
GetYMD()
{
SYSTEM_DATE=`date '+%Y%m%d'`
echo ${SYSTEM_DATE}
}
・ログ出力関数「LOG」
呼び出し元のファイル名($0)より、「basename」コマンドを使用して「.sh」を「.log」に変更したファイルに「printf」コマンドを使用して、引数で渡されたメッセージの内容を出力します。ファイル名の先頭に年月日、メッセージの先頭に年月日時分秒と呼び出し元のファイル名を付加しています。
・年月取得関数「GetYM」
「date」コマンドの年月フォーマットを取得して返却します。「return」では返却できない数値のため「echo」で返却しています。
・年月日取得関数「GetYMD」
「date」コマンドの年月日フォーマットを取得して返却します。「return」では返却できない数値のため「echo」で返却しています。
以下は、共通関数「sample.fnc」を読み込んで、処理を実行するサンプルです。
sample.sh
#!/bin/sh
# --共通関数ファイル読込--
. sample.fnc
# ログ出力
LOG "ログ出力のテスト開始"
# 年月取得
YM=`GetYM`
mkdir ${YM}
# 年月日取得
YMD=`GetYMD`
touch ${YMD}.dat
# ログ出力
LOG "ログ出力のテスト終了"
それでは実際に「sample.sh」を実行してみます。以下のような結果となります。
$ ls
sample.fnc sample.sh
$
$ sample.sh
$
$ ls -F
2006-02-07_sample.log 20060207.dat sample.sh*
200602/ sample.fnc
$
$ cat 2006-02-07_sample.log
2006-02-07 16:20:32 sample.sh ログ出力のテスト開始
2006-02-07 16:20:32 sample.sh ログ出力のテスト終了
$
↑先頭へ
ヒアドキュメントの利用
シェルスクリプトでもヒアドキュメントを使用することができます。ヒアドキュメントは、Perlなどの「cgi」を利用したホームページ作成などでよく使用されますが、構文は同じです。
ヒアドキュメントは、下記のような構文になります。
コマンド <<_EOF_
line1
line2
line3
_EOF_
シェルは「<<」を見つけると、それに続く文字列(上記例では_EOF_)を EOFマークとして覚えます。そして、その直後の行から次のEOFマークの直前の行までをコマンドへ順次渡していくという仕組みです。それではヒアドキュメントを「ftp」コマンドで使用するサンプルスクリプトを紹介します。
ftp_sample.sh
#!/bin/sh
HOST_NAME="ホスト名またはIPアドレス"
USER_NAME="ftpユーザー名"
PASSWORD="パスワード"
LOCAL_DIR="ローカル側の作業ディレクトリ"
GET_DIR="ftp先の作業ディレクトリ"
FILE_NAME="getするファイル名"
ftp -n ${HOST_NAME} << _EOF_
user ${USER_NAME} ${PASSWORD}
bin
lcd ${LOCAL_DIR}
cd ${GET_DIR}
get ${FILE_NAME}
bye
_EOF_
上記は、指定したホストに「ftp」で接続して、指定したファイルを取得するサンプルスクリプトです。取得するファイル名等を引数にすれば汎用的に使えると思います。
↑先頭へ
findコマンドの有効利用
ここでは、「find」コマンドを有効利用して、手動で行うような処理を自動化する方法を紹介します。例えば古いログファイル等を自動的に削除したい場合、findコマンドとcronを利用して自動化することができます。以下はそのサンプルです。
auto_del.sh
#!/bin/sh
find /home/usr/log -name '*.log' -mtime '+30' -exec rm -f {} \;
find /home/usr/log -type d -name '2*' -mtime '+60' -exec rm -r {} \;
1つ目のfindでは、拡張子が「.log」のファイルで、最終更新時刻が30日前のファイルを削除します。2つ目のfindでは、「2」で始まるディレクトリで、最終更新時刻が60日前のディレクトリをディレクトリごと削除します。
上記のスクリプトを「crontab」コマンドで定期的に起動するように登録しておくことで自動化できます。もちろん「crontab」のファイルに「find」コマンドを直接記述してもOKです。
↑先頭へ
リストファイルを読み込んで処理する
指定したファイルを1行毎に読み込んで処理する方法は、制御構文「while」にて解説したが、ここではその応用となるサンプルスクリプトを紹介する。
sample1.fnc
# --共通関数定義--
LIST=./abc.lst
# 文字列取得関数
GETSTR()
{
# 引数チェック
if [ $# -ne 1 ]
then
return 1
else
ID=$1
fi
# IDより文字列を探す
while read F1 F2
do
if [ "${F1}" = "${ID}" ]
then
echo ${F2}
break
fi
done < ${LIST}
}
上記は、「abc.lst」という外部ファイルから、引数で与えられた文字列をキーに対応する文字列を検索して返却する関数である。「abc.lst」ファイルの内容は以下のようになっています。
abc.lst
001 AAA
002 BBB
003 CCC
004 DDD
「abc.lst」ファイルは、2つのフィールドに分かれています。例えば、1行目はフィールド1が「001」、フィールド2が「AAA」となっています。各フィールド間は、スペースかTABで区切る必要があります。処理の流れは、「abc.lst」ファイルを1行ごとに読み込み、「while read」で2つのフィールドの文字列をそれぞれ「F1」と「F2」に格納します。引数で与えられた文字列「$ID」と「$F1」が一致した場合に「$F2」を「echo」コマンドで返却するという流れです。
下記は、上記関数を呼び出すサンプルスクリプトです。
sample1.sh
#!/bin/sh
# --共通関数ファイル読込--
. sample1.fnc
# 文字列取得
STR002=`GETSTR 002`
STR004=`GETSTR 004`
STR006=`GETSTR 006`
echo "STR002=${STR002}"
echo "STR004=${STR004}"
echo "STR006=${STR006}"
それでは実際に「sample1.sh」を実行してみます。以下のような結果となります。
$ sample1.sh
STR002=BBB
STR004=DDD
STR006=
$
↑先頭へ