HEARTBEATS

cacti 0.8.7hでハマった件の顛末

   

こんにちは。CTOの馬場です。

だいぶご無沙汰ですが、今回もインフラエンジニア向けにちょっとした情報を紹介します。

今回はcacti 0.8.7hでハマったので、その顛末と回避方法を書いておきます。

ハマった事象は 「データ取得は正常だけどrrdファイルが更新されない」 でした。。。

環境

  • CentOS 5.6
  • apache 2.2.21 (ソースインストール)
  • php 5.3.8 (ソースインストール)
  • MySQL 5.5.15 (本家謹製rpm)
  • cacti 0.8.7h + spine

イケてるtemplateが使いたかったので、better-cacti-templates を使えるように試行錯誤したのでした。

ログを集めた

何はなくともログです。ログ。

  • cactiのweb管理画面で Settings > General > Poller Logging Level をDEVELにしてログ確認
  • pollerの出力をファイルに出してチェック

すると、、、ログに下記の出力がありました。

  • CACTI2RRD: rrdtool update <filename> --template 99999:99999
  • ERROR: Not enough arguments

前者のほう、よくよく見るとrrdtoolのsyntaxが間違っている。よくよく見ると、本当は--templateの後は引数2つなんです。

rrdtoolのsyntax errorの結果、後者が出力されてました。 このせいでrrdファイルが更新されません。

回避策を探す

とりあえずエラーメッセージでググる。

Poller is missing template parameter according to cacti.log

すると、データ取得スクリプトの余計な空行を削除せよ、とのこと。

さっそくやってみると...効果なし。色々試しても効果なし。効果なし。なし。。

デバッグ

公式のデバッグマニュアルを見ながらデバッグ
manual:087:4help.2debugging - Cacti Docs

  1. Check Cacti Log File
  2. Check Basic Data Gathering
  3. Check Cacti's Poller
  4. Check MySQL Update
  5. Check RRD File Update

今までの調査で 5. はダメなのがわかっていて、 3. はokなのがわかっているので、 4. を実施。

Check MySQL Update

mysqlの設定を変更して全クエリを出力したのでした。
設定したら、 show variables して結果の確認を忘れずに!

  • set global log_slow_queries=On
  • set global long_query_time=0;

この状態でpollingが走ると、mysqlに対して実行された全クエリがスローログに出力されます。かなり大量なのでびっくりしてください。

実行されたクエリが取得できたら、データソースのIDを頼りに、 poller_output テーブルにデータを投入している箇所を探します。

INSERT INTO poller_output (local_data_id, rrd_name, time, output) 
VALUES ( データ ), ( データ ), ( データ ), ( データ ), ( データ ), ( データ ), ( データ ) 
ON DUPLICATE KEY UPDATE output=VALUES(output);

このクエリを手動でも実行してみて、データが正常に投入できているかどうか、取得できるかを確認します。

...今回はここは正常でした。明らかにオカシイ。まぁもともとオカシイから調べてるんですが。。。

ソース読み

公式マニュアルのお陰でMySQLが原因ではないことがわかったので、ハラを決めてソースを読みます。

今回はログに CACTI2RRD: rrdtool update 〜 と記載があり、ここがおかしいことはわかっていたので、この CACTI2RRD ととっかかりに調査します。

# find /var/www/cacti/ -type f -name "*.php"|xargs grep -nHi "CACTI2RRD"
/var/www/cacti/lib/rrd.php:80:          cacti_log("CACTI2RRD: " . read_config_option("path_rrdtool") . " $command_line", $log_to_stdout, $logopt);
/var/www/cacti/lib/rrd.php:399:                         cacti_log("CACTI2RRD: " . read_config_option("path_rrdtool") . " tune $data_source_path $rrd_tune");

2箇所しかない!ということで、rrd.phpを見てみます。

  • rrdtool_execute 関数の中で呼ばれているのがクサい
  • rrdtool_executeupdate の組み合わせで呼ばれている行を探す
  • rrdtool_function_update がクサい
  • → 呼んでいる箇所を探す。同じファイルにはないのでfindとxargsを組み合わせて探す
  • /var/www/cacti/lib/poller.php でしか呼んでない
  • /var/www/cacti/lib/poller.php を該当箇所からさかのぼって読む。読む。
  • → 実行されているはずのSQLが実行されていない!
  • → 分岐がおかしい!
  • is_hexadecimal関数の結果がおかしい!
  • → 定義されている箇所が見当たらないのでfindとxargsを組み合わせて探す
  • lib/functions.phpにあった!

と、いうわけで、 lib/functions.phpis_hexadecimal 関数を修正して対応完了。

コーディングミスで複数値対応ができなくなっていたようです。
(推測ですがipv6対応したかったもよう)

SVNみてみる

最新版(0.8.7のHEAD)では直ってる...

rev 6251→6252(2011/1/29)でエンバグして、rev 6850→6851(2011/10/9)に改修されてました。

まとめ

オープンソースでよかった。