2008年9月26日金曜日

cronとrun-partsを使って、任意の順番でスクリプトを実行する

Linux (確認はCentOS4と5) をインストールしたら、 "/etc/crontab" に最初からrun-partsの実行が登録してある。
※もしも入ってない場合は、特殊なケースかと思うけど、「crontab」 パッケージに入っているので入れます。
 

crontab はこんな感じ。
・
・
# run-parts
01 * * * * root run-parts /etc/cron.hourly
59 4 * * * root run-parts /etc/cron.daily
5 4 * * 0 root run-parts /etc/cron.weekly
9 4 1 * * root run-parts /etc/cron.monthly

 
 

run-parts ってなにさ


引数でディレクトリを指定すると、ディレクトリ内の実行可能ファイルを名前順に実行する コマンドです。
「run-parts /etc/cron.daily」 と指定があったら、 "/etc/cron.daily/"以下の実行対象を全部ですが一つずつ実行してくれます。
サブディレクトリは無視、あと、ファイル名も使える文字が決まってたはず、"英数-(ハイフン)_(アンダーバー)"あたりだったかな。
 
この名前順という性質は利用できる。
 
 

運用専用ディレクトリを作る


さて、run-parts に食わせる運用的なスクリプトの入れ物を作ります。
大体下記のような構成のツリーを作りますね、共通場所とログ場所は好みですけど作っといたほうがあとあとメンテナンスしやすいと思う。
work/ (cronの実行ユーザが読めればどこでもいい)
├config/ -----★共通設定ファイル置き場、"."(ドットコマンド)でスクリプトから読み込む
├logfiles/ -----★共通のログフォルダ
│
├dailyjob/
-----★日次で実行したいスクリプト入れ
└weeklyjob/ -----★週次で実行したいスクリプト入れ

 
 

dailyjob には何をいれるの?


使い方の一例としてはこんな感じ。

dailyjob/ 中身の例は下記ファイルたち
├00_timestamp -----★ログファイルに時刻書き込み
├05_serverstats -----★サーバのステータス出力とか
│10_stopapp -----★バックアップしたいアプリを止める
├20_appbackup -----★アプリデータのバックアップ
├30_startapp -----★止めていたアプリをスタート
└40_logbackup -----★ログなどのバックアップ

 

このケースで想定しているのは
「バックアップ前に動いてるアプリは止める必要がある、アプリは影響ある部分のバックアップが終わったらすぐ再開して、影響がない部分はゆっくりバックアップすることにしたい。また、バックアップはサーバの情報取得とかぶると重いからいや。」
という状況。(欲張りかも…)
 
ファイル名を数字で始めているので、実行される順番をコントロールできる。
あとはそれぞれのスクリプトをしっかり作っておけばOK、別々にCronだと、実行時間がかぶったりしたときの調整が大変なので、私は最近こんな感じで設定。
 
後から追加("05_" なんかはそう) できるようにちょっと数字は飛び飛びで設定しておくのもよいかもしれない。
"00_timestamp" は趣味で。
 
 

config/ ディレクトリに共通で読ませるファイルを置く


これも趣味だけど、ここに置くファイルにログファイルのパスとか使いまわせるファンクションを定義したファイルを置いておき、全部のスクリプトから "."(ドットコマンド) で読ませるようにする目的で使います。
 
もっと分かりやすいやり方もあるんでしょうけど、自分がメンテする分には今のところこの構成が楽かな。
 
ほか、run-partsは全部のスクリプトに共通の引数を渡すことができるので、例えば実行されるスクリプト側で 2 を渡せばデバッグ出力ONとか、1 もらわないと何もせず終了するなども共通で設定しておくといいかも。

Firefox3を自動更新したらアドオンが無効になったので、互換性チェックを一時 的に無効にする

Firefoxの 3.0.2 のリリースがあったので更新チェックをかけた。
3.0.3 がすぐに出たけど同じ方法で keyconfig は使えた。

 

それはいいんだけど、ボサッとしてたら大事な大事なアドオン、「keyconfig」が "3.0.2では対応してない" と、無効になってしまった。
正確に言うと更新前の確認で "keyconfig無効になりますよー" と教えてもらったけど、ちょっと我慢すればkeyconfigの更新があるだろうと軽くUpdate。
 

FireFox の再起動後、、、
Donutライクなファンクションキーでのタブ移動※が無かったら30秒と堪えられなかったので この keyconfig を有効にする手段を探す。

※ [Ctrl + (TAB|Shift + TAB)] or [Ctrl + (PageUP|Down)] にも同様の機能の割当てがあるけど、しっくりこない。

 


アドレス欄にabout:configを入力して、適当に "addon" とか "check" で絞り込む。
extensions.checkCompatibility というのがヒット。キー名をGoogleって調べたらこれっぽいね。
キーがないケースもある模様、その場合は 真偽値(ブーリアン)で作れとある。うちにはあったが何かのアドオンが作ってくれたのかな?
 

という事で、extensions.checkCompatibility の値をダブルクリックして「false」に変更。めでたしめでたし。
 

この手は自己責任で。
誤動作しそうなアドオンは開発者さんからのバージョンアップ(対応)を待つことを推奨、どーしてもいるやつだけ救済する目的で使いましょう。危ないのはとりあえず手動で無効に設定。

2008年9月24日水曜日

Googleが10周年で記念サイトオープンだそうな

Google10周年とのことで、記念サイトで歴史が一望できる。

Google 10th Birthday
http://www.google.com/tenthbirthday/


 

当時はYahoo! のようなディレクトリ型検索しか使ってなかった。
昔のロゴをみて思い出したけど、確か Google を見て「GeoCities がまた何かくだらんこと始めた」と思った記憶がある。
 

出だしの G しか合ってないやんか自分。

ネットワークビジュアライザでRIP、CCNAとかの勉強で

CCNAやらテクニカルエンジニア(ネットワーク) (※次年度からネットワークスペシャリスト) を受けようかなと思っているのにネットワークをやってない。
まあそれなりに知ってるしと思って学習サイト ping-t のCCNA問題をやったら 動的ルーティングがぼろぼろ だった、
そうだね、やってないし。いつもスタティックだったな。
 

と言うことで Network Notepadを使ってネットワーク図という記事で作ったネットワーク図で、RIP設定のお勉強をしてみる。
 

テストに使ったのは
会社保有の「CCNAバーチャルラボ Network Visualizer 5.0」

 
 

ネットワーク図を引いて、必要な設定を洗い出そう


[caption id="attachment_928" align="alignnone" width="300" caption="画像:今回のネットワーク図"]画像:今回のネットワーク図[/caption]
単純なネットワークだ。今回はルータ同士をFastEthernetで繋ぐ。
 

各ルータの設定要件は…
    ■ルータA
  • インターフェイス0 に 192.168.30.1/24

  • インターフェイス1 に 192.168.10.1/24

  • RIPで192.168.10.0 の情報を流す



    ■ルータB
  • インターフェイス0 に 192.168.30.2/24

  • インターフェイス1 に 192.168.20.1/24

  • RIPで192.168.20.0 の情報を流す



こんなもんか、ちなみにルータはCiscoの2600が使える。
 
 

ルータに設定を突っこもう_とりあえず全部のインターフェースまで



ルータAの設定、斜体はレスポンス
ルータの名前を「RouterA」、イーサネット0と1にIPアドレスを振る。
Router>enable
Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z
 
Router(config)#hostname RouterA
 
RouterA(config)#interface fastethernet 0/0
RouterA(config-if)#ip address 192.168.30.1 255.255.255.0
RouterA(config-if)#no shutdown
xx:xx:xx %LINK-3-UPDOWN: Interface Fastethernet0/0, changed state to up
xx:xx:xx %LINEPROTO-5-UPDOWN: Line protocol on Interface Fastethernet0/0, changed state to up
RouterA(config-if)#exit
 
RouterA(config)#interface fastethernet 0/1
RouterA(config-if)#ip address 192.168.10.1 255.255.255.0
RouterA(config-if)#no shutdown
xx:xx:xx %LINK-3-UPDOWN: Interface Fastethernet0/1, changed state to up
xx:xx:xx %LINEPROTO-5-UPDOWN: Line protocol on Interface Fastethernet0/1, changed state to up

RouterA(config-if)#exit

 

次はルータBの設定、斜体はレスポンス
ルータの名前を「RouterB」、イーサネット0と1にIPアドレスを振る。
Router>enable
Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z

Router(config)#hostname RouterA

RouterB(config)#interface fastethernet 0/0
RouterB(config-if)#ip address 192.168.30.2 255.255.255.0
RouterB(config-if)#no shutdown
xx:xx:xx %LINK-3-UPDOWN: Interface Fastethernet0/0, changed state to up
xx:xx:xx %LINEPROTO-5-UPDOWN: Line protocol on Interface Fastethernet0/0, changed state to up

RouterB(config-if)#exit

RouterB(config)#interface fastethernet 0/1
RouterB(config-if)#ip address 192.168.20.1 255.255.255.0
RouterB(config-if)#no shutdown
xx:xx:xx %LINK-3-UPDOWN: Interface Fastethernet0/1, changed state to up
xx:xx:xx %LINEPROTO-5-UPDOWN: Line protocol on Interface Fastethernet0/1, changed state to up

RouterB(config-if)#exit

 
 

で、この時点でのホストA(192.168.10.2)からの到達製をチェック。
◎→ルータAのインターフェイス 192.168.10.1 当然
◎→ルータAのインターフェイス 192.168.30.1 まあ順当
×→ルータBのインターフェイス 192.168.30.2 ルータBは帰りのルート(192.168.10.0宛)が分からない
×→ルータBのインターフェイス 192.168.20.1 ルータAは行き先のルート(192.168.20.0宛)が分からない
×→ホストBのインターフェイス 192.168.20.2 同上
 

ちなみにルータAのルーティングテーブルを表示するとこうなっている。
RouterA#show ip route
 
Gateway of last resort is not set
C 192.168.30.0/24 is directly connected, FastEthernet0/0
C 192.168.10.0/24 is directly connected, FastEthernet0/1

 

RIPを設定してみる


手始めにルータBからRIPのアナウンスをさせる。
RouterB>enable
RouterB#configure terminal
RouterB(config)#router rip
RouterB(config-router)#network 192.168.20.0

 
そうするとRIPのパケットをブロードキャストし始める。
RouterB#debug ip rip
RIP protocol debugging is on
 
*9 23 23:16:58.221: RIP: sending v1 update to 255.255.255.255 via FastEthernet0/0 (192.168.30.2)
*9 23 23:16:58.221: RIP: build update entries
*9 23 23:16:58.221: subnet 192.168.20.0 metric 1
*9 23 23:16:58.221: RIP: sending v1 update to 255.255.255.255 via FastEthernet0/1 (192.168.20.1)
*9 23 23:16:58.221: RIP: build update entries - supressing null update

インターフェイス0 からは 192.168.20.0 の情報を、インターフェイス1からは何も送ってない。
この時点でルータAには192.168.20.0の宛先情報が届いているのが パケットモニタ で確認できるんだけど、このままでは受け入れずに破棄されてしまう。
 
 

で、ルータAにも同様にRIPを設定したら、ルータAのルーティングテーブルはこうなる。
RouterA#show ip route
 
Gateway of last resort is not set
R 192.168.20.0 [120/1] via 192.168.30.2, 00:00:20, FastEthernet0/0
C 192.168.30.0/24 is directly connected, FastEthernet0/0
C 192.168.10.0/24 is directly connected, FastEthernet0/1

 
ルータBはこう
RouterB#show ip route
 
Gateway of last resort is not set
R 192.168.10.0 [120/1] via 192.168.30.1, 00:00:17, FastEthernet0/0
C 192.168.20.0/24 is directly connected, FastEthernet0/1
C 192.168.30.0/24 is directly connected, FastEthernet0/0

 

Cはコネクテッド:接続しているネットワーク、RはRIPによって学習されたネットワーク、設定できている模様。
 
 

到達性を確認してみる


さて、ローカルだけのスタティックな設定では問題が2つあった。
●ルータAは行き先のルート(192.168.20.0宛)が分からない
●ルータBは帰りのルート(192.168.10.0宛)が分からない
 

これらはルーティングテーブルを見る限り、RIPによって解決された。
と言うことでホストAからの到達性を再度確認してみる。
 
◎→ルータAのインターフェイス 192.168.10.1 当然
◎→ルータAのインターフェイス 192.168.30.1 まあ順当
◎→ルータBのインターフェイス 192.168.30.2 ルータBは帰りのルート(192.168.10.0宛)をRIPによって学習した
◎→ルータBのインターフェイス 192.168.20.1 ルータAは行き先のルート(192.168.20.0宛)をRIPによって学習した
◎→ホストBのインターフェイス 192.168.20.2 同上
 
ホストAから登場するすべてのIPアドレスにPingが飛ぶのを確認した、オールグリーン。
次はRIPの要素を整理したい。そしてOSPFだな、とりあえずシングルサイトで。

2008年9月23日火曜日

なんとなくWindowsでC言語プログラミング_(2)

「なんとなくPシリーズ」タグを作って続行。タイトルは 続 → 新 → … と続けたかったがやめておく。
一応コンセプトとしてはC言語を勉強してLinuxカーネルソースに迫ろうとしているのだが、果たして。
 
 

前回のなんとなくWindowsでC言語プログラミングで思い出したものがある。
「こんにちはマイコン」、1982年!の本。次は折角なのでそれっぽいことをやってみよう。
変数のお勉強でたしかこんなコード、N-88 Basic だっけ?
10 INPUT "ナマエ ヲ ニュウリョク";A$
20 PRINT A$;"ノ アホー"
(30 goto 20)
※3行目gotoもしたかったけど、今回大分話がそれていくのでパス。
 
キーボードから文字列の入力を促し、変数に代入。それを標準出力から表示する単純なプログラムだ。
これの下りは面白かった記憶がある。
 

ついでなのでbatで再現


[sourcecode language='bash']
@echo off
set /P name="ナマエ ヲ ニュウリョク"
:10
echo %name% ノ アホー
goto 10
[/sourcecode]
簡単だが、やはりこれでは展開がない。
 
 

それではCで再現


main(void)とコメントを覚えた。
[sourcecode language='c']
#include

int main(void) {
char name[8]; /*メモリ8バイト確保!*/
printf("ナマエ ヲ ニュウリョク");
scanf("%s",name); /*入力をnameのポインタのとこに並べる*/
printf("%sノ アホー\n",name); /*nameの中身を出力*/
return 0;
}

[/sourcecode]

収穫は変数の宣言とscanfのおかげでポインタがなんとなく分かった事。

実行してみる。
>inputter.exe
ナマエ ヲ ニュウリョクarashi
arashiノ アホー

上々。
 
char宣言で8バイトメモリを確保、アドレスの情報をポインタとしてnameに格納しているというわけかいな。
 

実験タイム1


ほなここで実験してみよう、変数2つ宣言したら並ぶの?
[sourcecode language='c']
#include

int main(void) {
char name[8]; /*メモリ8バイト確保!*/
char name1[8]; /*同様にname1を宣言する*/
printf("ナマエ ヲ ニュウリョク");
scanf("%s",name);
printf("%sサンハ テンサイ\n",name);
printf("%x\n",&name); /*nameのアドレス*/
printf("%x\n",&name1); /*name1のアドレス*/
return 0;
}

[/sourcecode]


>inputter.exe
ナマエ ヲ ニュウリョクsatoru
satoruサンハ テンサイ
12ff64
12ff6c


えーと、8バイトだからー。 12ff64 から 12ff6b までで8バイト、次は 12ff6c から、、合ってる。並んでるね。
 

実験タイム2


入出力で実験、入力してない変数を出力するとか。
[sourcecode language='c']
#include

int main(void) {
char name[8];
char name1[8];
printf("ナマエ ヲ ニュウリョク");
scanf("%s",name);
printf("%sサンハ テンサイ\n",name);
printf("%sノ アホー\n",name1); /*入力してないname1を出力する*/
return 0;
}
[/sourcecode]

実行する、まずは普通の入力
>inputter.exe
ナマエ ヲ ニュウリョクippata
ippataサンハ テンサイ
3n@ノ アホー

3n@ てなんじゃらほい。確保したメモリに元からあった情報と言うことらしいけど、まあ0で埋めるなりの初期化すれば問題ないことが分かった。
 

でも次の入力。20文字入れてみる。
>inputter.exe
ナマエ ヲ ニュウリョク123456789a123456789b
123456789a123456789bサンハ テンサイ
9a123456789bノ アホー

ああああぁ、は、はみ出したーー
scanf()に脆弱性が、っていうのはテクニカルエンジニアで習ったけどこういうことか、ものすごく納得。
とはいえ、狙ったコードの実行は至難の技にも見えるんだけど、どうなんだろう。なんか手法が確立されてるんだろうか。
 
 

そして脱線へ


これはどうやって動いているんだろうと思ったのでちょっと追う。
WindowsのCコンパイラは "/Fa" というオプションをつけたらアセンブリリストのファイルを作ってくれる。
で、作ってみた。ちょっと省略してこんな感じ。
_main PROC
; File c:\cprog\inputter.c
; Line 3
push ebp
mov ebp, esp
sub esp, 20 ; 00000014H
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
mov DWORD PTR __$ArrayPad$[ebp], eax
; Line 6
push OFFSET $SG2471
call _printf
add esp, 4
; Line 7
lea eax, DWORD PTR _name$[ebp]
push eax
push OFFSET $SG2472
call _scanf
add esp, 8
; Line 8
lea ecx, DWORD PTR _name$[ebp]
push ecx
push OFFSET $SG2473
call _printf
add esp, 8
; Line 9
lea edx, DWORD PTR _name1$[ebp]
push edx
push OFFSET $SG2474
call _printf
add esp, 8
; Line 10
xor eax, eax
; Line 11
mov ecx, DWORD PTR __$ArrayPad$[ebp]
xor ecx, ebp
call @__security_check_cookie@4
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END

 

うーん。。まさにこれは全部書いてあるんだろうけど、次回だな。
 
 

しかし カーネル への道のはずなんだが。。。やっぱり遠回りなのでは。
そうだコンテキストスイッチというのはこれを切り替えているんだろうなと言うことでまとめよう。

2008年9月22日月曜日

なんとなくWindowsでC言語プログラミング

Linuxのカーネルコードを読みたいと思ったんだが、家にLinuxないしC読めない。
じゃあどうしよう。
 
 

まずMicrosoftがCの開発環境をタダで配っているので自宅のWindows XP SP2にインストールしてみる。

Microsoft Visual C++ 2008 Express Edition
http://www.microsoft.com/japan/msdn/vstudio/express/default.aspx


 

うむ、インストール問題無し。
 
では "hello.c" としてc言語のファイルを適当なテキストエディタで書く。
 

標準入出力の関数色々はいったヘッダファイル "stdio .h" を取り込んでー
正常終了に0を返す main 関数を一個書いて名前をつけて保存、"hello.c"
[sourcecode language='c']
# include

int main() {
printf("Hello Work!\n");
return 0;
}
[/sourcecode]

 

付属のCコンパイラらしきツール "cl.exe" でコンパイルしよう。
>cl hello.c
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.


hello.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.


/out:hello.exe
hello.obj

 

よし、 "hello.exe" が完成したぞ、早速実行だ。
>hello.exe
Hello Work!

 

ようし問題なし。
 
 

あとはシステムコールを把握するために C言語の勉強しながら "stdio.h" を読み解いてー
Windowsのカーネルソースを想像して、Linuxに当てはめてー
POSIXに思いを馳せて行けばよいのかしら。。。
 

!? 。これはもしやすごく遠回りしているのではなかろうか?

2008年9月21日日曜日

Microsoft Network Monitor 3.2 がリリースされているじゃないか

よい機能をつけてきた模様。WireShrkで十分?まあそう言わないで。
 

開発さんのブログ:Network Monitor 3.2 has arrived!
http://blogs.technet.com/netmon/archive/2008/09/17/network-monitor-3-2-has-arrived.aspx
 
ダウンロードは:Microsoft Network Monitor 3.2
http://www.microsoft.com/downloads/details.aspx?FamilyID=f4db40af-1e08-4a21-a26b-ec2f4dc4190d&DisplayLang=en


 

更新の目玉はアプリ別のフィルタ標準搭載、開発さんのブログでは画像付きで紹介されてます。
Process Tracking: Now you can identify rogue applications sending network data! View all the processes on your machine generating network traffic (process name and PID). Use the conversation tree to view frames associated with each process.
引用:開発さんのブログより

 

ほかはAPIを実装したとかPCAP形式サポートとか。
 
 

WireShark (WinPCAP)入れたくないサーバとかではMS製のモニタ使うので機能アップは地味に嬉しいかも。