SSブログ

サーバ管理者のためのプログラミング入門(シェルプログラミング基礎4~シェルスクリプト変数その2) [サーバ管理者のプログラミング]

 前アーティクルにおいて一通り変数の使い方を紹介したが、さらに重要な特殊な(?)変数がある。これらの変数はシェルスクリプトを作成してゆく中で重要な役割を担うので覚えておいてもらいたい。

その1:$?

 変数の名前に「?」というものがある。
 これは、「直前に実行されたコマンドの、終了ステータス」が獲得できる変数となっている。

 「終了ステータス」とはどういうことか。それは、要するにコマンドが正常終了したか否かを判断できるもの…と理解してもらってもまあ差し支えないと思う。

 実例を見てみよう。たとえば、pingコマンドで試す。pingが通った場合から見てみよう。
[root@kagami ~]# ping -c 1 localhost
PING kagami (127.0.0.1) 56(84) bytes of data.
64 bytes from kagami (127.0.0.1): icmp_seq=1 ttl=64 time=0.159 ms

--- kagami ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.159/0.159/0.159/0.000 ms
[root@kagami ~]# echo $?
0

 localhostにpingを投げている例。当然応答があるので正常な実行結果ということになる。
 pingコマンドの直後に$?の内容を確認すると「0」が入っていることが判る。
 ほとんど全てのコマンドは、「0」が入っていたときはコマンドは正常に終了したことを表している。

 続いて、機器の存在しないIPアドレスに対してpingコマンドを実行したらどうなるか。
[root@kagami ~]# ping -c 1 192.168.10.99
PING 192.168.10.99 (192.168.10.99) 56(84) bytes of data.

--- 192.168.10.99 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

[root@kagami ~]# echo $?
1

 今度は「1」が入っていた。
 コマンドとしては異常終了していることを意味している。

 続いて、hostsやDNSで名前解決できない場合はというと…
[root@kagami ~]# ping null.void
ping: unknown host null.void
[root@kagami ~]# echo $?
2

 今度は「2」になっている。
 pingコマンドは、異常終了した場合「終了ステータス」に異常だった理由を入れている。まあ、あまり深く気にすることはそう多くないと思うが。

 というわけで、「$?」が0だったか、0じゃなかったか…によって、コマンドが正常に終了したか、異常終了したかが判断できるのであった。



その2:$!

 今度は、変数名「!」について。
 これは「直前に実行したバックグラウンドプロセスのPID」を意味する。

 これも実例を見てみよう。
 sleepコマンドをバックグラウンドで実行して、そのPIDを調べてみると…
[root@kagami ~]# sleep 60000 &
[1] 4485
[root@kagami ~]# echo $!
4485

 このように、バックグラウンドで実行されているであろうsleepコマンドのPIDが表示され、一致している。
 本当に一致しているか、psコマンドで確認してみると…
[root@kagami ~]# ps -ef | fgrep "4485"
root      4485  1390  0 17:31 pts/0    00:00:00 sleep 60000
root      4487  1390  0 17:31 pts/0    00:00:00 fgrep 4485

 fgrepコマンドも一緒に引っかかっているが、確かにsleepコマンドのPIDそのものである。

 killコマンドでsleepコマンドを強制終了させてみる。
[root@kagami ~]# kill 4485
[root@kagami ~]#
[1]+  終了しました      sleep 60000
[root@kagami ~]# ps -ef | fgrep "4485"
root      4489  1390  0 17:31 pts/0    00:00:00 fgrep 4485

 間違いなくsleepコマンドが消えてなくなった。

 この変数はバックグラウンドでコマンドを実行中に別のことを実行するなどする際に役立つ。



その3:$$

 続いて変数名「$」。これは、「現在実行中のコマンドラインインタプリタ…つまりshとかbashとか…のPID」を意味する変数になる。

 これも実例から見てみよう。
[root@kagami ~]# echo $$
1390
[root@kagami ~]# ps -ef | fgrep 1390
root      1390  1386  0 Jan18 pts/0    00:00:00 -bash
root      4496  1390  0 17:38 pts/0    00:00:00 ps -ef
root      4497  1390  0 17:38 pts/0    00:00:00 fgrep 1390

 子プロセスも表示されているが、変数「$$」に入っている数値1390は、bashのPIDと確かに一致していることがわかる。
 では、現在のbashから、さらに子プロセスとしてbashを実行するとどうか。
[root@kagami ~]# bash -c 'echo $$;ps -ef | fgrep $$'
4501
root      4501  1390  0 17:40 pts/0    00:00:00 bash -c echo $$;ps -ef | fgrep $$
root      4502  4501  0 17:40 pts/0    00:00:00 ps -ef

 先ほどと同じターミナルで実行しているが、別の数値が表示されている。同時に実行したpsコマンドにも4501というPIDでbashが表示されている。

 PIDが変化してしまった?という疑いを晴らすため、再度確認してみるが…
[root@kagami ~]# echo $$
1390
[root@kagami ~]# ps -ef | fgrep 1390
root      1390  1386  0 Jan18 pts/0    00:00:00 -bash
root      4506  1390  0 17:42 pts/0    00:00:00 ps -ef
root      4507  1390  0 17:42 pts/0    00:00:00 fgrep 1390

 やはり同じPIDで変化していないことが確認できた。



その4:位置パラメータ

 今度は、「位置パラメータ」の出番。
 「$」記号に続けて数値を記述すると、それは「位置パラメータ」を示す変数となる。
 「$1」は一番目のパラメータ、「$2」は二番目のパラメータ…「$3」なら三番目のパラメータ…という具合。

 「位置パラメータ」とはそもそも何?という人もいるだろう。簡単に言うと、コマンドに続けて記述しているオプションや引数のことである。たとえば、「ls -la /tmp」というコマンドを例にとると、
  ・最初の「ls」…コマンド名 (実は、「$0」という変数にこの名前が入っている)
  ・オプション「-la」…第1パラメータ → これは「$1」に入っている
  ・引数「/tmp」…第2パラメータ → これは「$2」に入っている
 こんな具合だ。簡単なシェルスクリプトで実際に試してみよう。

 まず、以下のようなシェルスクリプトを用意してみた。
#!/bin/sh

echo 0","$0
echo 1","$1
echo 2","$2
echo 3","$3

 chmod +xして、とりあえず実行してみよう。すると…
[root@kagami ~]# /tmp/param_test.sh
0,/tmp/param_test.sh
1,
2,
3,

 こんな具合に。

 では、適当にパラメータとか記述してみるとどうなるだろか。
[root@kagami ~]# /tmp/param_test.sh konata miyuki tsukasa
0,/tmp/param_test.sh
1,konata
2,miyuki
3,tsukasa

 パラメータを3個並べてみると、それぞれ1~3にそれぞれの文字列が入っていることが判る。これが「位置パラメータ」である。(C/C++的表現では「argv」に相当する)


 で、この「位置パラメータ」が何個列挙されているか知りたいこともあるだろう。そのような情報を格納するのが変数「$#」である。

 先ほどのシェルスクリプトを以下のように改造してみよう。
#!/bin/sh

echo "#,"$#
echo 0","$0
echo 1","$1
echo 2","$2
echo 3","$3

 これを先ほどと同じように実行すると…
[root@kagami ~]# /tmp/param_test.sh
#,0
0,/tmp/param_test.sh
1,
2,
3,
[root@kagami ~]# /tmp/param_test.sh konata miyuki tsukasa
#,3
0,/tmp/param_test.sh
1,konata
2,miyuki
3,tsukasa

 引数を何も書かずに実行すると、変数「$#」には0が。3個つけて実行すると変数「$#」には3が入っている。これによって、「位置パラメータの個数」を知ることが可能となるのである。(C/C++的表現では「argc」に相当している)

 また、「位置パラメータ」を分割せずにそのままの形で欲しい!という時もある。そのような時には変数「$*」を用いると良い。
 先ほどのシェルスクリプトをさらに改造する。
#!/bin/sh

echo "#,"$#
echo 0","$0
echo 1","$1
echo 2","$2
echo 3","$3

echo "*,"$*

 これを再度同じように実行すると…
[root@kagami ~]# /tmp/param_test.sh
#,0
0,/tmp/param_test.sh
1,
2,
3,
*,
[root@kagami ~]# /tmp/param_test.sh konata miyuki tsukasa
#,3
0,/tmp/param_test.sh
1,konata
2,miyuki
3,tsukasa
*,konata miyuki tsukasa

 …という具合になる。

 ひとまず覚えておきたい基本的な変数はこんなところかな。

 次はいよいよプログラミングっぽい感じのすることをやってみることとする。
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。