2013年12月28日土曜日

FTPクライアントは転送が失敗してもリターンコードが0な理由をさぐる

会社の先輩から「FTPはファイル転送が失敗しても気付けないから気付けろ!」と注意を受けた。
 「そんな馬鹿な」と思って調べていくと、どうやらそれが「常識」らしい。。。

再現させてみた

とりあえず本当かどうか目で見るまで信じられなかったので、再現を試みることに。

意外とあっさり再現できた。

まずftp.confを用意する ftp.confの内容
open 192.168.1.2
user fetaro P@ssw0rd
bin
prompt
get CentOS-5.6-i386-bin-DVD.iso
bye
次に、設定ファイルをftpクライアントに食わせてコマンドを実行
# ftp -n < ftp.conf
この時、ファイル転送中にサーバをkillしたりすると、
[root@localhost ~]# ftp -n < ftp.conf
Interactive mode off.
OOPS: child died
[root@localhost ~]# echo $?
0
まじかよ!ほんとに0だ。
ちなみにサーバが起動していなくてもリターンは0だ。
なんて不親切なんだFTPクライアント!

なぜそうなっているのか


なぜこんなことになっているか気になったので、C言語はあまり得意じゃないけど、ソースコードを調べてみることにした。 ソースコードのRPMをダウンロード。
# wget http://ftp.redhat.com/redhat/linux/enterprise/6Server/en/os/SRPMS/ftp-0.17-54.el6.src.rpm
RPMをインストールして中身を確認。
# rpm -ivh ftp-0.17-54.el6.src.rpm
# cd rpmbuild/SOURCES/
# ls 
netkit-ftp-0.17-C-Frame121.patch
netkit-ftp-0.17-fprintf.patch
netkit-ftp-0.17-runique_mget.patch
(略)
netkit-ftp-0.17.tar.gz
パッチと本体が入っているので、本体を解凍。
# tar zxvf netkit-ftp-0.17.tar.gz
# cd netkit-ftp-0.17/ftp
# ls
Makefile  cmds.c  cmds.h  cmdtab.c  domacro.c  ftp.1  ftp.c  ftp_var.h  glob.c  glob.h  main.c  netrc.5  pathnames.h  ruserpass.c
main.c の中を見ていくと、main関数の最後はコマンドをパースする無限ループがある。
101 int
102 main(volatile int argc, char **volatile argv)
103 {
(略)
217         for (;;) { # ←ここがコマンドをパースする無限ループ
218                 cmdscanner(top);
219                 top = 1;
220         }
221 }
うーん。
この無限ループは抜け道がいないということは、cmdscanner関数の中のどこかでexitしているということになる。。。

C言語はこういう実装が普通なんだろうか、なんて追いにくいんだ。。。

この中を追って行ってもらちがあかなそうだったので、調査方法を変えてexitをgrepすることにした。
[root@localhost netkit-ftp-0.17]# grep -r "exit(" *
ftp/cmds.c:1505:                exit(1);
ftp/cmds.c:1732:        exit(0);
ftp/cmds.c:1790:        exit(1);
ftp/main.c:115:         exit(1);
ftp/main.c:175:                         exit(0);
ftp/main.c:180:                         exit(1);
ftp/main.c:207:                 exit(0);
意外に少なくexit(1)は4か所。
それぞれ見ていくとexit(1)に至る処理は以下の場合であることがわかった。

  •  "ftp: ftp/tcp: unknown service" のエラーが出るとき 
  •  "unknown option" のエラーが出るとき 
  •  shell関数の中 (ただしshell関数は呼ばれていなそう) 
  •  fatal関数の中 (Out of memoryの時っぽい) 

というわけで、上記の4パターン以外はftpクライアントは0でリターンするようだ。

結論!


FTPクライアントはメモリが溢れるか、オプションを間違えない限りは0リターン!
(と思われる)

ruby の ftpクライアント使おうっと。。。

2013年11月14日木曜日

MongoDBのEnterprise版って実は無料で落とせるんですよ

あまり知られていないけれども、MongoDBのEnterprise版って無料で落とせます。

普通に、MongoDB社のホームページに行って、一番下にあるDownload Enterprise MongoDB Editionのリンクをクリックして、名前などを入れれば落とす画面に行けます。

MongoDB Enterprise版だとSNMPができるので、それを触ってみたくて落としました。
他にもEnterprise版はケルベロス認証にも対応しているみたいだけど、これは誰得なんだろう。


ちなみに同じページからEnterprise版のMongoDBだけでなく、MMS(MongoDB Monitoring System)のオンプレ版のRPMもダウンロードできます。

これはわざわざインターネットのMMSを使わないでも自前でMMSが使えるらしいので、ぜひ試してみたいが、それは今度の機会に。

2013年3月26日火曜日

ZabbixでMongoDBを監視する

表題の通りZabbixでMongoDBを監視してみようと思います。 環境
  • Zabbix Server
    • CentOS release 6.2 (Final)
    • zabbix-server 1.8.16-1.el6.JP.x86_64
    • mikoomi mongodb plugin (Rev 78)
  • MongoDB & Zabbix Agent
    • CentOS release 6.3 (Final)
    • MongoDB 2.2.1

はじめに

今回は、mikoomiさんに作っていただいたMongoDB Zabbixテンプレートを使います。
仕組みとしては、zabbixのextentionにMongoDBドライバをつかったPHPのスクリプトを置き、PHPのスクリプトがMongoDBに接続して、各種ステータスをクエリでとってきて、zabbixに渡すというもの(zabbix-agentは使いません)。 これにより、時系列でのクエリ件数やらいろんな統計情報が取得できます。

[処理シーケンス]
Zabbix --> Zabbixテンプレート --> PHPスクリプト --> MongoDB-PHPドライバ --> MongoDB

手順

基本的にmikoomiさんブログ通り進めていきます。 ZabbixとMongoDBのインストールは割愛します。

MongoDB-PHPドライバのインストール

まず、必要なライブラリをyumでインストール。
# yum install php-devel php-pear gcc make
次に、Mongo-phpドラインをインストール
# pecl install mongo
最後に/etc/php.iniに以下の行を追加。
extension=mongo.so
MongoDB-PHPドライバの稼働確認には以下のスクリプトを書いて、phpで実行し、成功するかどうかを確認すればOKです。
<?php
new MongoClient("mongodb://server:27017");
?>

Zabbix-MongoDB監視テンプレートのインストール

まず、mikoomiさんの作ったphpとshをzabbixのexternalscriptsに置きます(私がとったときはSVNのリビジョンは78でした。) そして、実行権限を与えます。
# cd /etc/zabbix/externalscripts/
# wget http://mikoomi.googlecode.com/svn/plugins/MongoDB%20Plugin/mikoomi-mongodb-plugin.php
# wget http://mikoomi.googlecode.com/svn/plugins/MongoDB%20Plugin/mikoomi-mongodb-plugin.sh
# chmod 755 mikoomi-mongodb-plugin.*
# chwon zabbix:zabbix mikoomi-mongodb-plugin.*
次に、このZabbixテンプレートのXMLをダウンロードして、zabbixのテンプレートに追加します。これで完了です。

MongoDBのサーバをZabbixAgentとして登録

まず、Zabbixのホストを追加して、「リンクしているテンプレート」に「Template_MongoDB」を選択します。
次に、これが唯一のハマりどころ(※)ですが、「マクロ」のところに、以下の二つの値を定義します。
  • マクロ = "{$SERVER}" , 値 = MongoDBのサーバのIPアドレス
  • マクロ = "{$PORT}" , 値 = MongoDBのポート番号

これで以下の図のようにMongoDBの各種統計情報がとれていると思います。


※)ハマりどころについて

mikoomiさんのブログには{$MONGODB_HOSTNAME}、{$MONGODB_PORT}、{$MONGODB_ZABBIX_NAME}の3つの値をマクロにセットしろと書いてあるんですが、これだとうまくいきません。phpやshにうまく引数が渡りません。
テンプレートのXMLをみると
item type="10" key="mikoomi-mongodb-plugin.sh[-h {$SERVER} -p {$PORT} -z {HOSTNAME}]" value_type="3"
と書いてあるので、ここに合わせて{$SERVER}と{$PORT}を定義したところうまく動きました。

2013年1月5日土曜日

git pushでThe requested URL returned error: 403

githubにpushしようとしたところ、以下のエラーがでた。
The requested URL returned error: 403 
これはgitのプロトコルをsshではなくhttpでクローンしたため、pushすることができなかった。sshでクローンしたら問題なくできた。

こんな単純なことで結構はまってしまいましたので、情報共有まで。