ホーム » 2022 » 7月 » 07

日別アーカイブ: 2022年7月7日

2022年7月
 12
3456789
10111213141516
17181920212223
24252627282930
31  

最新の投稿(電子情報)

アーカイブ

カテゴリー

シェルスクリプトの演習

今回は、前回までのシェルの機能を使って演習を行う。

プログラムの編集について

演習用のサーバに接続して、シェルスクリプトなどのプログラムを作成する際のプログラムの編集方法にはいくつかの方式がある。

  • サーバに接続しているターミナルで編集
    • nano , vim , emacs などのエディタで編集
  • パソコンで編集してアップロード
    • scp 命令で編集したファイルをアップロード
  • パソコンのエディタのリモートファイルの編集プラグインで編集
    • VSCode の remote-ssh プラグインを使うのが簡単だけど、サーバ側の負担が大きいので今回は NG

リモート接続してエディタで編集

今回の説明では、emacs で編集する方法を説明する。

((( Emacs を起動 )))
guest00@nitfcei.mydns.jp:~$ emacs helloworld.sh

エディタが起動すると、以下のような画面となる。

scpでファイルをアップロード

scpコマンドは、ssh のプロトコルを使ってネットワークの先のコンピュータとファイルのコピーを行う。前述の emacs などのエディタが使いにくいのなら scp を使えばいい。

((( scp 命令の使い方 )))
$ scp ユーザ名@ホスト名:ファイルの場所 

((( サーバの helloworld.sh をダウンロード )))
C:\Users\t-saitoh> scp -P 443 guest00@nitfcei.mydns.jp:helloworld.sh .
C:\Users\t-saitoh> scp -P 443 guest00@nitfcei.mydns.jp:/home0/Challenge/3-shellscript/helloworld.sh .
((( パソコンの hoge.sh をアップロード )))
C:\Users\t-saitoh> scp -P 443 hoge.sh guest00@nitfcei.mydns.jp:
((( パソコンの hoge.html を public_html にアップロード ))) 
C:\Users\t-saitoh> scp -P 443 hoge.html guest00@nitfcei.mydns.jp:public_html

シェルスクリプトの命令

条件式の書き方

シェルには、test コマンド( [ コマンド ) で条件判定を行う。動作の例として、テストコマンドの結果を コマンドの成功/失敗 を表す $? を使って例示する。

guest00@nitfcei:~$ [ -f helloworld.sh ] ; echo $?    # [ -f ファイル名 ]
0                                                    # ファイルがあれば0/なければ1
guest00@nitfcei:~$ [ -x /bin/bash ]; echo $?         # [ -x ファイル名 ]
0                                                    # ファイルが存在して実行可能なら0/だめなら1
guest00@nitfcei:~$ [ -d /opt/local/bin ] ; echo $?   # [ -d ディレクトリ名 ]
1                                                    # ディレクトリがあれば0/なければ1
guest00@nitfcei:~$ [ "$PATH" = "/bin:/usr/bin" ] ; echo $?   # [ "$変数" = "文字列" ]
1                                                    # $変数が"文字列"と同じなら0/違えば1

シェルの制御構文

((( シェルの if 文 )))
if [ -f helloworld.sh ]; then
   echo "exist - helloworld.sh"
elif [ -f average.c ]; then
   echo "exist - average.c"
else
   echo "みつからない"
fi
((( シェルの for 文 )))
for user in /home0/guests/*   # ワイルドカード文字 * があるので、/home0/guests/ のファイル一覧
do                            # が取り出されて、その1つづつが、$user に代入されながら繰り返し。
    echo $user
done
---
結果: /home0/guests/guest00, /home0/guests/guest01 ... 
((( while 文 )))
/bin/grep ^guest < /etc/passwd \    # passwd ファイルでguestで始まる行を抜き出し、
| while read user                   # read コマンドで その 行データを $user に代入しながらループ
  do
      echo $user
  done

シェル演習向けのコマンド一例

`コマンド`と$(コマンド)

((( コマンドの結果を使う )))
guest00@nitfcei:~$ ans=`whoami`     # whoami コマンドの結果を ans に代入
guest00@nitfcei:~$ echo $ans        # バッククオートに注意 ' シングルクオート " ダブルクオート ` バッククオート
guest00
guest00@nitfcei:~$ ans=$(pwd)       # pwd コマンドの結果を ans に代入
guest00@nitfcei:~$ echo $ans        # 最近は、$(コマンド) の方が良く使われている
/home0/guest00

コマンドライン引数

シェルの中でコマンドライン引数を参照する場合には、”$数字“, “$@” を使う。$1 , $2 で最初のコマンドライン引数, 2番目のコマンドライン引数を参照できる。すべてのコマンドライン引数を参照する場合には、$@ を使う。

((( argv.sh : コマンドライン引数を表示 )))
#!/bin/bash
echo "$@"
for argv in "$@"
do
    echo "$argv"
done
((( argv.sh を実行 )))
guest00@nitfcei:~$ chmod 755 argv.sh
guest00@nitfcei:~$ ./argv.sh abc 111 def
abc 111 def          # echo "$@" の結果
abc                  # for argv ... の結果
111
def

cutコマンドとawkコマンド

((( 行の特定部分を抜き出す )))
guest00@nitfcei:~$ cut -d: -f 1 /etc/passwd   # -d:  フィールドの区切り文字を : で切り抜き
root                                          # -f 1 第1フィールドだけを出力
daemon
adm
:
guest00@nitfcei:~$ awk -F: '{print $1}' /etc/passwd  # -F: フィールド区切り文字を : で切り分け
root                                                 # ''
daemon
adm
:

lastコマンド

((( ログイン履歴を確認 )))
guest00@nitfcei:~$ last
t-saitoh pts/1        64.33.3.150      Thu Jul  7 12:32   still logged in
最近のログインした名前とIPアドレスの一覧
:
((( guest* がログインした履歴 )))
guest00@nitfcei:~$ last | grep guest
guest15  pts/11       192.156.145.1    Tue Jul  5 16:00 - 16:21  (00:21)
:
((( 7/5にログインしたguestで、名前だけを取り出し、並び替えて、重複削除 )))
guest00@nitfcei:~$ last | grep guest | grep "Jul  5" | awk '{print $1}' | sort | uniq
7/5("Jul  5")の授業で演習に参加していた学生さんの一覧が取り出せる。
### あれ、かなりの抜けがあるな!?!? ###

whoisコマンド

((( IPアドレスなどの情報を調べる )))
guest00@nitfcei:~$ whois 192.156.145.1
:
inetnum:        192.156.145.0 - 192.156.148.255
netname:        FUKUI-NCT
country:        JP
:
guest00@nitfcei:~$ whois 192.156.145.1 | grep netname:
netname:   FUKUI-NCT
netname:   ANCT-CIDR-BLK-JP

シェルスクリプトのセキュリティ

ここまでのプログラムの動作例では、a.out などのプログラムを実行する際には、先頭に “./” をつけて起動(./a.out)している。これは「このフォルダ(“./“)にある a.out を実行せよ」との意味となる。

いちいち、カレントフォルダ(“./”)を先頭に付けるのが面倒であっても、環境変数 PATH を “export PATH=.:/bin:/usr/bin” などと設定してはいけない。こういった PATH にすれば、”a.out” と打つだけでプログラムを実行できる。しかし、”ls” といったファイル名のプログラムを保存しておき、そのフォルダの内容を確認しようとした他の人が “ls” と打つと、そのフォルダの中身を実行してしまう。

guest00@nitfcei:~$ export PATH=".:/bin:/bin/bash"
guest00@nitfcei:~$ cat /home0/Challenge/1-CTF.d/Task5/Bomb/ls
#!/bin/bash

killall -KILL bash
guest00@nitfcei:~$ cd /home0/Challenge/1-CTF.d/Task5/Bomb
guest00@nitfcei:~$ ls
# 接続が切れる(bashが強制停止となったため)

こういったシェルスクリプトでのセキュリティのトラブルを防ぐために、

  • 環境変数PATHに、カレントフォルダ”./”を入れない
  • シェルスクリプトで外部コマンドを記述する際には、コマンドのPATHをすべて記載する。
    コマンドのPATHは、which コマンドで確認できる。echo とか [ といったコマンドは、bash の組み込み機能なので、コマンドのPATHは書かなくていい。

演習問題

シェルスクリプトの練習として、以下の条件を満たすものを作成し、スクリプトの内容の説明, 機能, 実行結果, 考察を記載したワードファイル(or PDF)等で、こちらのフォルダに提出してください。

  • スクリプトとして起動して結果が表示されること。(シバン,実行権限)
  • コマンドライン引数を使っていること。
  • 入出力リダイレクトやパイプなどを使っていること。
  • 以下の例を参考に。
((( 第1コマンドライン引数指定したユーザが、福井高専からアクセスした履歴を出力する。)))
#!/bin/bash

if [ -x /usr/bin/last -a -x /bin/grep ]; then   # [ ... -a ... ] は、複数条件のAND
    /usr/bin/last "$1" | /bin/grep 192.156.14
fi
-------------------------------------------------------------------------
((( guest グループで、$HOME/helloworld.sh のファイルの有無をチェック )))
#!/bin/bash

for dir in /home0/guests/*
do
   if [ -f "$dir/helloworld.sh" ]; then      # PATHの最後の部分を取り出す
      echo "$(/usr/bin/basename $dir)"       # $ basename /home0/guests/guest00
   fi                                        # guest00                  ~~~~~~~basename
done

UMLと振る舞い図

前回の講義で説明した構造図に続いて、処理の流れを説明するための振る舞い図の説明。

講義の後半は、UML作成のレポートの課題時間とする。

振る舞い図

参考資料をもとに振る舞い図の説明を行う。

ユースケース図

1507131131_211x192.png

ユーザなど外部からの要求に対する、システムの振る舞いを表現するための活用事例や機能を表す図がユースケース図。 システムを構築する際に、最初に記述するUMLであり、システムに対する処理要件の全体像や機能を理解するために記述する。 ユーザや外部のシステムは、アクターとよび人形の絵で示す。楕円でシステムに対する具体的な処理をユースケースとして楕円で記述する。 関連する複数のユースケースをまとめて、サブジェクトとして示す場合もある。

アクティビティ図

処理順序を記述するための図にはフローチャートがあるが、上から下に処理順序を記述するため、縦長の図になりやすい。また、四角枠の中に複雑なことを書けないので、UMLではアクティビティ図を用いる。

初期状態●から、終了状態◉までの手順を示すためのものがアクティビティ図。 フローチャートに無い表現として、複数の処理を並行処理する場合には、フォークノードで複数の処理を併記し、最終的に1つの処理になる部分をマージノードで示す。 通常の処理は、角丸の長方形で示し、条件分岐はひし形で示す。

ステートチャート図(状態遷移図)

ステートチャート図は、処理内部での状態遷移を示すための図。 1つの状態を長丸長方形で示し、初期状態●から終了状態◉までを結ぶ。 1つの状態から、なんらかの状態で他の状態に遷移する場合は、分岐条件となる契機(タイミング)とその条件、およびその効果(出力)を「契機[条件]/効果」で矢印に併記する。 複数の状態をグループ化して表す場合もある。

シーケンス図

複数のオブジェクトが相互にやり取りをしながら処理が進むようなもののタイミングを記述するためのものがシーケンス図。 上部の長方形にクラス/オブジェクトを示し、その下に縦軸にて時系列の処理の流れの線(Life Line)を描く。 オブジェクトがアクティブな状態は、縦長の長方形で示し、そのLife Line間を、やり取り(メッセージ)の線で相互に結ぶ。 メッセージは、相手側からの返答を待つような同期メッセージは、黒塗り三角矢印で示す。 返答を待たない非同期メッセージは矢印で示し、返答は破線で示す。

コミュニケーション図

クラスやオブジェクトの間の処理とその応答(相互作用)と関連の両方を表現する図。

応答を待つ同期メッセージは -▶︎、非同期メッセージは→で表す。複数のオブジェクト間のやりとりの相互作用を表現する。

タイミング図

タイミング図は、クラスやオブジェクトの時間と共に状態がどのように遷移するのかを表現する図。

状態変化の発生するタイミングや、時間的な遅れや時間的な制約を図で明記するために使われる。

IT専科・UML入門より引用