情報工学実験
1
Shallscript
と
gnuplot
学籍番号 J04055: 宮城 隼人
実験実施日:5 月 6 日 (金)
提出日:5 月 16 日 (月)
締切日:5 月 13 日 (金)
1
本実験の目的
• (楽をするために) なるべく自動化を. • ミスを防ぎやすくなる. • 作業記録としても有用.2
実験
2.1
Level-1
2.1.1 ソース及び実行結果 ################# #myls ∼ソース∼# ################ #!/bin/sh #引数の数を調べる if [ $# -eq 0 ] ; then #引数が 0 の場合 pw=’.’elif [ $# -eq 1 ] ; then #引数が 1 の場合 pw=$1
else #引数が 2 以上
echo "Too much" fi
#引数で受け取ったフォルダが存在しない場合 if [ ! -e $pw ] ; then
echo "$pw:No such file or Directory" exit
fi
#引数で受け取ったのがフォルダでない場合 if [ ! -d $pw ] ; then
echo "$pw:No such file or directory" exit
fi
#ファイルの一覧を取得 files=‘ls -1 $pw‘
#ディレクトリを表示 for FILE in $files do
if [ -d $pw/$FILE ] ; then echo "$FILE/"
fi done
#ファイルを表示 for FILE in $files do if [ -f $pw/$FILE ] ; then echo "$FILE" fi done ---########## #実行結果## ########## [nw0455:3st/scr/log] j04055% ls
access_log myls* myls~* myyy* sample/
[nw0455:3st/scr/log] j04055% myls sample/ access_log myls myls~ myyy
[nw0455:3st/scr/log] j04055% myls sample ls/ make-sample/ make-sample.tar.gz sample-script.tar.gz [nw0455:3st/scr/log] j04055% cd /usr/local/bin [nw0455:/usr/local/bin] j04055% ls myls* 2.1.2 動作説明 mylsは指定したディレクトリ・ファイル内容を表示するスクリプトである。処理手順は以下の 通りになっている。 1. 引数の個数チェックを行う。0 個ならカレントディレクトリ、1 個なら引数を内容を pw に設 定する。また、2 個以上ならエラーで終了する。
2. 引数の内容チェックを行う。引数で指定した内容が存在しないか、ファイルならエラーで終 了する。 3. pwに設定したディレクトリの内容一覧を取得する。 4. ディレクトリだけを表示する。表示する際/を付け足す。 5. ファイルだけを表示する。 ちなみに、myls のパスを通しておいたので、どのディレクトリからも実行可能である。
2.2
Level-2
2.2.1 ソース及び実行結果 ##################### # myupper ∼ソース∼ # ##################### #!/bin/sh #引数の個数を調べる if [ $# -lt 1 ] ; then #引数がなければエラー echo "Usage: myupper parametar1 parametar2" exit fi #引数を一つずつ取り出して実行する for file do if [ -f $file ] ; then #ファイルなら大文字に変換 mv $file ‘echo $file | tr ’[a-z] ’[A-Z]’‘ elseecho "error: $file is not file" #ファイルでなければエラー fi done ---################### # mymv ∼ソース∼ # ################### #!/bin/sh
#引数の値を調べる
if [ ! $# -eq 2 ] ; then #引数が 2 個でなければエラー echo "Usage: mymv new-t old-t"
exit fi
for file in *.$2 #引数 2 で指定した拡張子のつくファイルを file に格納 do
if [ -f $file ] #ファイルなら拡張子を変換のプロセスに移行 then
chfile1=‘( basename $file .$2)‘ #拡張子を取り除く
chfile2=$chfile1.$1 #引数 1 で指定した拡張子を追加する mv $file $chfile2 #拡張子を変換
else
echo "error: $file is not file" #ファイルでなければエラー fi ---########## #実行結果## ########## [nw0455:~/zikken1/2st] j04055% ls
Knapsack2/ apache_1.3.33/ data1 test.obj Knapsack2.tar.gz apache_1.3.33.tar.gz make-sample/ test.png
[nw0455:~/zikken1/2st] j04055% myupper data1 test.obj
[nw0455:~/zikken1/2st] j04055% ls
DATA1 Knapsack2.tar.gz apache_1.3.33/ make-sample/ Knapsack2/ TEST.OBJ apache_1.3.33.tar.gz test.png
[nw0455:~/zikken1/2st] j04055% mymv tiff png
[nw0455:~/zikken1/2st] j04055% ls
DATA1 Knapsack2.tar.gz apache_1.3.33/ make-sample/ Knapsack2/ TEST.OBJ apache_1.3.33.tar.gz test.tiff
2.2.2 動作説明
まずは、myupper から見てゆく。myupper はファイルを引数に入力して、大文字に変換するス クリプトである。引数のチェックは myls と同様に行うが、myupper ではいくつかのコマンドを復
号して利用している。大文字によって変換される手順は以下の通りになる。 1. echoコマンドで引数で受け取ったファイル名を出力 2. —を使って、連続で tr コマンドを実行する。その際の正則表現によって、a∼z の小文字を 大文字に変換するのでファイル名が大文字になる。 3. mvコマンドの引数 2 に、大文字化されたファイル名が代入される。 4. mvコマンドで、ファイル名が引数 1 →引数2に変換される。 次に、mymv コマンドを見る。これは引数1に追加したい拡張子、引数2に変更したい拡張子を 指定して変換するスクリプトである。つまり引数2→引数 1 になる。引数 2 で指定された拡張子が 付いてるファイルは全て指定される。拡張子が変換される手順は以下の通りである。 1. 引数2で指定された拡張子のついたファイルが変数 file に格納される 2. 変数 chfile1 に basename コマンドによって拡張子を除かれたファイル名を代入する。 3. 変数 chfile2 に引数 1 の拡張子を追加して格納する。 4. mvコマンドによって拡張子が変換されたファイル名に改名
2.3
Level-3
2.3.1 ソース及び実行結果 #file: thumnail4.sh#syonopsis: thumbail4.sh SUFFIX RESIZE PHOTONUM #comment: SUFFIXで指定した拡張子を持つ画像ファイルの # 縮小画像を生成し、 # 表示する HTML ファイルを生成。 #!/bin/sh #引数チェック if [ $# -lt 3 ] ; then #オプション数が合ってなかったらエラーメッセージを表示 echo "Usage: $0 SUFFIX RESIZE PHOTO_NUM"
echo " RESIZE: persent"
echo " example> thumnail3.sh jpg 30 4" fi #リストアップ処理 SUFFIX=$1 #拡張子を指定 RESIZE=$2 #ファイルの倍率を指定 PHOTO_NUM=$3 #HTML1ページあたりの画像ファイルの指定数 files=‘ls *.SUFFIX‘ #指定された拡張子のついたファイルを全て収納
#縮小画像の生成
#縮小画像保存用の一時ディレクトリ生成 DIR=resized #縮小画像のディレクトリを指定 if [ -d $DIR ] ; then
#既にそのディレクトリがあればメッセージを表示 echo " terporal directory ($DIR) exists..." else #なければ新しく DIR で指定したディレクトリ名で作る
mkdir $DIR
echo "temporal directory ($DIR) CREATED." fi
#一時ディレクトリに縮小画像を生成 cd $DIR #DIRに移動
for filename in $files #filesの数だけ繰り返す do
#コンバートで元の画像データをサイズを変更して修正を行う
#変換後のファイル名は../で上のディレクトリの画像ファイルに_s を付け足したもの convert -resize $RESIZE%*$RESIZE% ../$filename ${filename}_s.$SUFFIX echo "covert $filename to $DIR/${filename}_s.$SUFFIX
done cd ../ #元にいたディレクトリに戻る PAGE=1 #ページ数 FLAG=1 #HTMLの先頭と最後の部分の判定用の変数 PLAG=1 #画像ファイル数 resized_files=‘ls $DIR/*_s.$SUFFIX #修正し直したファイルを取得 for filename in $resized_files
do
if [ $FLAG -eq 1 ] ; then #HTMLファイル生成
#HTML開始
# >>で HTML ファイルに出力
echo "<html>" > page$PAGE.html echo "<head>" >>page$PAGE.html
echo "<title>thumbnail page$PAGE.html</title>" >> page$PAGE.html echo "</head>" >> page$PAGE.html
echo "<body>" >> page$PAGE.html FLAG=0
echo "<img src="$filename\">" >> page$PAGE.html #画像表示タグを生成 #画像と引数 3 で指定した枚数と img で生成した数が一致したときに実行
if [ $ PLAG -eq $PHOTO_NUM ] ; then
FLAG=1 #1にすることによって HTML の終了部分を生成するようにセット PLAG=0 #ページ当たりのファイル数をリセットし直す
fi
if [ $FLAG -eq 1 ] ; then #HTML終了
echo "</body>" >> page$PAGE.html echo "</html>" >> page$PAGE.html echo " page$PAGE.html makes." PAGE=‘expr $PAGE + 1‘ fi PLAG=‘expr $PLAG + 1‘ #一回ループが終わると 2 枚目、3 枚目・・・というふうになる done ---########### # 実行結果 # ########### [nw0455:3st/scr/thumbnail] j04055% ls DSC00030.jpg DSC00160.jpg thumbnail2-sample.html thumbnail4.sh* DSC00057.jpg DSC00204.jpg thumbnail2.sh* DSC00076.jpg rep/ thumbnail3-sample.html DSC00149.jpg thumbnail1.sh* thumbnail3.sh* [nw0455:3st/scr/thumbnail] j04055% thumbnail4.sh jpg 10 3 temporal directory (resized) CREATED.
convert DSC00030.jpg to resized/DSC00030.jpg_s.jpg convert DSC00057.jpg to resized/DSC00057.jpg_s.jpg convert DSC00076.jpg to resized/DSC00076.jpg_s.jpg convert DSC00149.jpg to resized/DSC00149.jpg_s.jpg convert DSC00160.jpg to resized/DSC00160.jpg_s.jpg convert DSC00204.jpg to resized/DSC00204.jpg_s.jpg page1.html makes. page2.html makes.
2.3.2 動作説明 まず、引数チェックを行う。チェックにかからなければ次に進む。コマンド部で、HTML に張り 付けたい画像ファイルの拡張子を引数 1 に指定する。引数 2 にサイズをパーセント単位で設定し、 引数3に 1 ページ内に納める写真数を指定する。 次に指定された拡張子のファイルのリストを取得し、変数 files に格納する。そして、画像を縮小 画像を保存するためのディレクトリを作成し、そこに縮小画像を生成して保存する。それらのリス トは resized files に格納される。最後に HTML ファイルを生成する。この例の場合、1 ページ当た りに 3 枚の画像ファイルが設定され全部で 6 枚なので HTML ファイルは 2 つになる。この例の処 理手順は以下の通り。 1. HTMLファイルの 1 ページ目の開始部分を生成。FLAG=0 を設定される。 2. 縮小後の画像ファイルの 1 枚目を表示するタグを生成。 3. どの if 文にもかからなかったので PLAG+1(2) して次のループに移動。 4. 2枚目の画像表示タグを生成。PLAG+1(3) して次のループに移動。
5. 3枚目の画像表示タグを生成。PLAG と引数3 (PHOTO NUM) が一致するので FLAG=1,PLAG=0 に設定。 6. FLAGが 1 に設定されたので 1 ページの HTML の終了部分を生成。PAGE(ページ数) を 2 に設定。POINT+1(1) に設定。 7. HTMLファイルの 2 ページ目の開始部分を生成。FLAG を 0 に設定。 8. 4枚目の画像表示タグを生成。PLAG+1(2) として次にループに移動 9. 5枚目の画像表示タグを生成。PLAG+1(3) として次にループに移動 10. 6枚目の画像表示タグを生成。PLAG と引数3が一致するので FLAG=1,PLAG=0 に設定。 11. HTMLファイルの 2 ページ目の終了部分を生成。PAGE(ページ数) を 3 に設定。POINT+1(1) に設定。 12. ファイル数は 6 なのでここでループは終了する。
2.4
Level-4.1and2
2.4.1 ソースと実行結果 ################# # log ∼ソース∼ # ################# #!/bin/sh if [ -f $2 ] ; thencase "$1" in -all) #アクセスの総数 #|→直前のコマンドが実行できたら次のコマンドを同じファイルに順次実行する #1.cut→ファイルの各行のスペースで区切られた最初のフィールドを切り取る #2.wc→-l で行数 (アクセス総数) だけを表示する a_num=‘cut -d ’ ’ -f 1 $2 | wc -l‘ echo "アクセスの総数は$a_num です" exit;; -data) #日毎のアクセス数 *日は順番通りならんでるのでソートの必要なし #1.cut→ all と同じだが、フィールドは 4 番目 ([ ] でくくられた部分) を切り取る #2.tr→ [を削除する 例:[21 → 21 #3.cut→コロンで区切られた 1 番目のフィールド (日付け) を切り取る #例:21/Dec/2004:08:46:08 + 0900] → 21/Dec/2004 * [は 2 で削除済み #4.uniq→-c オプションで重複してる行をカウントする
d_num=‘cut -d ’ ’ -f 4 $2 | tr -d [ | cut -d ’:’ -f 1 | uniq -c echo "$d_num" exit;; -ip) #IP毎のアクセス数 #1.cut→ all と同じ #2.IPアドレスを昇順に並べ替える #3.uniq→-data と同じ
i_num=‘cut -d ’ ’ -f 1 $2 | sort -n | uniq -c‘ echo "$i_num"
exit;;
*) #オプションが入力されてない場合
echo "Usage : [ option ] [ filename ]" echo "option [ -all ] [ -data ] [ -ip ]" esac
else
echo "$2 is not file"
---########### # 実行結果 # ###########
[Hayato-Miyagi:scr/sample-script/log] ./log -all access_log
アクセスの総数は 95です
[Hayato-Miyagi:scr/sample-script/log] j04055 ./log -ip access_log 1 35.10.47.37 3 60.34.136.173 1 61.116.186.45 2 61.199.170.156 1 61.213.47.211 6 61.78.61.166 1 61.95.54.174 1 64.53.90.33 2 66.196.90.178 1 66.196.90.207 5 66.196.90.59 1 66.196.90.92 1 66.196.91.132 1 66.196.91.175 1 66.196.91.178 1 66.196.91.199 1 66.196.91.202 1 66.196.91.203 2 66.196.91.205 1 66.196.91.206 2 66.196.91.207 2 66.196.91.216 7 66.196.91.239 1 66.196.91.32 1 66.196.91.87 1 68.121.94.147 1 68.143.54.82 4 82.67.110.170 2 82.79.189.243 1 133.13.48.235 1 133.13.48.8 1 133.13.49.18 2 133.13.50.76
1 133.13.52.37 1 133.13.53.122 2 133.13.54.156 2 133.13.54.53 3 133.13.57.226 2 133.95.109.80 1 210.139.250.215 1 210.47.27.36 1 218.113.200.138 1 218.146.238.174 1 219.160.252.142 5 219.166.179.56 3 220.109.8.237 5 220.110.222.75 3 220.20.70.41 1 220.221.238.133 2 220.221.239.196
[Hayato-Miyagi:scr/sample-script/log] j04055% ./log -data accesslog 7 06/Dec/2004 1 08/Dec/2004 76 09/Dec/2004 2 10/Dec/2004 1 13/Dec/2004 2 15/Dec/2004 1 17/Dec/2004 2 21/Dec/2004 3 22/Dec/2004 2.4.2 動作説明 このスクリプトは access log に記載されたデータを解析するためのものである。 コマンドの書式は log[-オプション][ファイル名] として行い、オプションでアクセス総数を種別亊に 分けることができる。指定できるオプションは-all=アクセス総数、-ip=IP 毎のアクセス数、-data= 日毎のアクセス数となっている。 スクリプトで使われてるコマンドは以下の通りである。 1. cutコマンド:指定された場所を切り取るためのコマンド 2. wcコマンド:ファイルの行数、単語数、サイズを表示 3. sortコマンド:文字列をソートする 4. trコマンド:文字の置換を行う 5. uniqコマンド:連続する同じ行を 1 行にまとめる apacheの access log では
82.67.110.170 - - [21/Dec2004:08:46:08 +0900] ∼ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ IPアドレス 日時 となっている。スペースで区切った場合、フィールドの 1 番目が IP アドレスとなり、4 番目が日 時になる。 コロンで区切ると、フィールドの 1 番目は日付けだけで時間は表示されない。
2.5
Level4.3
2.5.1 ソースと実行結果 ################################## # gploのソース (日毎のグラフを作成) # ################################## #!/bin/sh FILE=access_log #日付けを切り取り, 7 06/Dec/2004 の形式で抜き取るDAIRY=‘cut -d ’ ’ -f 4 $FILE | tr -d [ | cut -d ’:’ -f 1 | uniq -c‘ echo " " > $1.data
# 7 06/Dec/2004 → 06/Dec/2004 7 に変換するための処理
#このように変換すれば gnuplot でグラフを容易に作成することができる FLAG=1
for daily in $DAIRY do
if [ $FLAG -eq 1 ] ; then W=$daily
FLAG=0 else
echo "$daily $W" >> $1.data FLAG=1
fi done
#gnuplotへのセット部分
echo "set terminal postscript eps" > $1.gnuplot #出力を eps 形式にセットする echo "set output \"$1.eps\"" >> $1.gnuplot #$1.eps のファイルに出力 echo "set xdata time" >> $1.gnuplot #日付け型に変更
echo "set timefmt \"%d/%b/%Y\"" >> $1.gnuplot #時刻形式を日:略称:年にする echo "plot \"$1.data\" using 1:2 notitle with boxes" >> $1.gnuplot#図を作成 gnuplot < $1.gnuplot #gnuplotに出力
---############
# 実行結果 # ###########
[nw0455:scr/sample-script/log] j04055% gplo tod access_log tod.data tod.eps tod.gnuplot
[nw0455:scr/sample-script/log] j04055% cat tod.data 06/Dec/2004 7 08/Dec/2004 1 09/Dec/2004 76 10/Dec/2004 2 13/Dec/2004 1 15/Dec/2004 2 17/Dec/2004 1 21/Dec/2004 2 22/Dec/2004 3 図 2: 日毎のグラフ 2.5.2 動作説明
gploのスクリプトは access log から日毎のアクセス数を解析し、その結果から自動的に gnuplot のグラフを作成する機能がある。
まず日付けのデータを切り取り、.data 形式のファイルに出力する。そしてコメントに書いてある ようにデータの順番を交替する。こうすると時刻を x 軸にセットするのが容易になる。