タグ・アーカイブ: 小ネタ

前のエントリーでping監視の1行コマンドを書きましたが、pingコマンドのオプションで気になったことをメモ。

まず、「-s 1」で1バイトのパケットを投げてるのに、どうして
9 bytes from 192.168.0.1: icmp_seq=0 ttl=255
みたいなレスポンスが帰ってくるかっていうと、「8バイトのICMPヘッダと1バイトのパケットの合計」なので、辻褄があうのです。試しに1バイトのパケットを投げたときの出力結果と8バイトのパケットを投げたときの出力結果を比較してみましょう。

■ 1バイトのパケットを投げたとき

$ ping -c 1 -s 1 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 1(29) bytes of data.
9 bytes from 192.168.0.1: icmp_seq=0 ttl=255

--- 192.168.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
, pipe 2

■ 8バイトのパケットを投げたとき

$ ping -c 1 -s 8 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 8(36) bytes of data.
16 bytes from 192.168.0.1: icmp_seq=0 ttl=255 time=0.552 ms

--- 192.168.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.552/0.552/0.552/0.000 ms, pipe 2

このように、自分が投げたパケットサイズにプラスして、8バイトのヘッダがくっつくのです。

あと、jmanのping(8)の項目を見て思ったのですが、

> -s packetsize
>
何バイトのデータが送られるかを指定する。デフォルトは 56 で、
ICMP
ヘッダの 8 バイトを加えて、
> 64 バイトの
ICMP
データになる。
スーパーユーザーだけがこのオプションを使用できる。

ってあるんだけど、rootじゃないのにこのオプション使えてるのです。どーでもいーっちゃいーんだけど気になったので、
手元の端末でmanを見てみた。

$ man ping
(中略)
> -s packetsize
> Specifies  the number of data bytes to be sent.  The default is 56, which translates into 64 ICMP data bytes when combined with
> the 8 bytes of ICMP header data.

とだけ書いてあるので、特にスーパーユーザーでないとこのオプションが使えないってわけじゃないのかなーと。
ちなみに、(っ´∀`)っ ゃーのマシンにインストールされているpingのバージョンは

$ ping -V
ping utility, iputils-ss020927

で、pingコマンドが含まれているパッケージ「iputils」のバージョンは

$ rpm -q iputils
iputils-20020927-19.EL4.5

です。

タイトルのまんま、複数のホストにpingを打ってその結果をわかりやすく出力してみたくなったので、
一行大好きな(っ´∀`)っ ゃーは、pingを打つ対象をfor文でグルグルまわし、pingが通ったら「生きてるよー」
死んでたら「死んでるよー」と出力するようにしました。
以下の例は、192.168.0.1から192.168.0.8まで、それぞれに1発ずつ1バイトのパケットを投げて
pingによる死活監視をし、終了ステータスから判断して生きてたら「(時刻)(TAB)~~~ is alive」、
死んでたら「(時刻)(TAB)~~~ is dead」という返事をさせます。
$ for i in 192.168.0.{1..8}; do ping  -c 1 -s 1 $i | grep "bytes from" > /dev/null ; if [ 0 -eq `echo $?` ]; then echo `date`$'t'$i' is alive'; else echo `date`$'t'$i' is dead' ; fi; done
出力結果(例)は以下の通りです。
Fri May 2 17:21:12 JST 2008     192.168.0.1 is alive
Fri May 2 17:21:15 JST 2008     192.168.0.2 is dead
Fri May 2 17:21:15 JST 2008     192.168.0.3 is alive
Fri May 2 17:21:18 JST 2008     192.168.0.4 is dead
Fri May 2 17:21:21 JST 2008     192.168.0.5 is dead
Fri May 2 17:21:24 JST 2008     192.168.0.6 is dead
Fri May 2 17:21:27 JST 2008     192.168.0.7 is dead
Fri May 2 17:21:30 JST 2008     192.168.0.8 is dead
コマンドの途中に、pingの出力を/dev/nullに捨てていますが、もし「 > /dev/null」がないと、以下のようになります。
$ for i in 192.168.0.{1..8}; do ping  -c 1 -s 1 $i | grep "bytes from" ; if [ 0 -eq `echo $?` ]; then echo `date`$'t'$i' is alive'; else echo `date`$'t'$i' is dead' ; fi; done
9 bytes from 192.168.0.1: icmp_seq=0 ttl=255
Fri May 2 17:24:57 JST 2008     192.168.0.1 is alive
Fri May 2 17:25:00 JST 2008     192.168.0.2 is dead
9 bytes from 192.168.0.3: icmp_seq=0 ttl=64
Fri May 2 17:25:00 JST 2008     192.168.0.3 is alive
Fri May 2 17:25:03 JST 2008     192.168.0.4 is dead
Fri May 2 17:25:06 JST 2008     192.168.0.5 is dead
Fri May 2 17:25:09 JST 2008     192.168.0.6 is dead
Fri May 2 17:25:12 JST 2008     192.168.0.7 is dead
Fri May 2 17:25:15 JST 2008     192.168.0.8 is dead
ちょっと見づらいですね。

いつもいつも、configファイルを編集するのに、私の場合はviで既存の行をコピーしてコメントアウトし、その真下に変更後の内容を書きます。こうすることで、変更履歴がわかりやすくなるのと、万が一元に戻す必要がある場合に楽だからです。

今までviでyypしてたりしてたのですが、シェルスクリプトなどで行う際に、なるべく対話式じゃないやり方でできないかなーと思ったのです。そこで思いついたのが、sedを使う方法。

まず、hogeというファイルのaaaという行をコメントアウトして、aaaとbbbの間にabcを挿入するという例でやってみます。

sh-3.00$ cat hoge
aaa
bbb
ccc
ddd
eee

それでは、いざ置換!

sh-3.00$ sed s/aaa/#aaa'n'abc/g hoge
#aaa
abc
bbb
ccc
ddd
eee

こうすることで、aaaの行がコメントアウトされ、aaaとbbbの行の間にabcが挿入されました。
けど、aaaという行が複数あって、どこか1箇所だけ置換したい・・・って場合は、、、
誰か教えてくださいorz
「sed 改行 置換」でググったら2chのスレにそのものズバリな答えが出てきたのでできました。

例えば、「aaa<改行>bbb」は置換せずに、「aaa<改行>ccc」は「#aaa<改行>abc<改行>ccc」にしたいという場合、

sh-3.00$ sed -n '${p;q};:s; N;s/aaanccc/#aaanabcnccc/;P;D;b s' hoge
aaa
bbb
#aaa
abc
ccc
ddd
eee

これでできます!
これで、例えば新しくサーバ作ったときに、sshd_configでrootの直接sshログインを禁止したりするのに役立ちそうです。

# cd /etc/ssh
# cp -p sshd_config sshd_config.orig

【rootでのsshログインを禁止する】
# sed -i s/#PermitRootLogin yes/#PermitRootLogin yes'n'PermitRootLogin no/g sshd_config

【X11転送を禁止する】
# sed -i s/#X11Forwarding no/X11Forwarding no/g sshd_config
# sed -i s/X11Forwarding yes/#X11Forwarding yes/g sshd_config

【接続元の名前解決にDNSを使わない】
# sed -i s/#UseDNS yes/#UseDNS yes'n'UseDNS no/g sshd_config

これをシェルスクリプトに組み込んでやれば、人間が介在する手間を最小限に、設定ファイルの編集ができそうです。