Nagios/Web I/Fからコマンド実行でエラー 

NagiosのWeb I/Fでコマンド実行させようとするとエラーが出るので直したい。

こんな感じ

Error: Could not open command file '/usr/local/nagios/var/rw/nagios.cmd' for update!

Nagiosデーモンは適切なユーザ/グループで実行している。「open出来ねー」と言われたファイル(パイプ)も、適切な権限。nagios用グループを作ってapacheユーザとnagiosユーザを含めている。

# ps -eo pid,user,rgroup,command | grep nagios
3254 nagios nagios /usr/local/nagios/bin/nagios -d /usr/local/nagios/etc/nagios.cfg
# ls -alF /usr/local/nagios/var/rw/
合計 8
drwxrwsr-x 2 nagios nagcmd 4096 2月 17 09:03 ./
drwxrwxr-x 4 nagios nagcmd 4096 2月 17 09:26 ../
prw-rw---- 1 nagios nagcmd 0 2月 17 09:03 nagios.cmd|
# grep nagcmd /etc/group
nagcmd:x:201:apache,nagios
#

けど、apacheはnobodyで実行されているのは良いのかなぁ?

# ps -ef |grep httpd
root 3280 1 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3282 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3283 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3284 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3285 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3286 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3287 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3288 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3289 3280 0 09:04 ? 00:00:00 /usr/sbin/httpd
nobody 3307 3280 0 09:05 ? 00:00:00 /usr/sbin/httpd
root 3583 3168 0 09:30 pts/2 00:00:00 grep httpd
#

ここが原因ぽいんだけど。nobody権限で実行していたら駄目だよねぇ。試しにユーザnobodyをグループnagcmdへ追加してapacheを再起動して試してみる。

# usermod -a -G nagcmd nobody
# grep nagcmd /etc/group
nagcmd:x:201:apache,nagios,nobody
# service httpd restart
httpd を停止中: [ OK ]
httpd を起動中: [ OK ]
#

ありゃー、うまくいっちゃったよ。でもnobodyをnagcmdに追加しておくわけにはいかないよね...どうするのが普通なわけ? みじんこれべるとかいくつかのサイトを見ると

chmod o+rw /usr/local/nagios/var/rw/nagios.cmd

って書いてあるけど、それって駄目じゃん。正解は明らかにapacheのCGI実行ユーザをnagcmdへ参加させておくことで、しかもそれをnobodyではなくてapache専用にすることだよね。httpd.confで指定すれば出来るんだっけ? httpdの親プロセスはroot権限なのだけど、それは実際のコネクションを待ち受ける子プロセスを作るだけしかしてくれなくて、子プロセスはnobody権限なので頑張ったってapache権限に昇格したりしないぜ? ということでapacheの実行ユーザをnobodyからapacheへ変更することで対応することとした。
/etc/httpd/conf/httpd.confをこんな感じに書き換えてapacheを再起動。

# egrep -e '^#?(User|Group)' /etc/httpd/conf/httpd.conf
User apache
Group apache
#User nobody
#Group nobody
#service httpd restart
(略)
#


これでうまくいった。

ちょっと気になるのはapacheの実行ユーザを変更したのだけれど、それで不具合が出ていないかどうかはチェックすらしていないことだね。あとでnobody権限での実行を前提にしたソフトをいじる必要が出てきたらどうするんだろう、nagiosの方で妥協してchmod o+rw nagios.cmdするのかしら。

Nagios入れてみた 

Nagios入れてみた。
案の定、Webインタフェースは期待していたのと違うんだよなぁ。
少しいじって何とかならないか見てみよう。

そそそ、tmpwatchを設定して/tmpのゴミ掃除を自動化しなきゃ。

最近の監視ツール 

最近は監視ツールって何が使われているのかしら。とりあえずZABBIXとかNagios辺り、パフォーマンス監視で各種グラフを用意したい場合にはRRD Toolとかは別途必要、とかなんだろうか。

muninって何するんだ? ググってみると...ふむぅ、MRTG的なものね。

それにしてもどの情報源も古いな、3年以上昔のものが多い。枯れているのは良いことなんだけど、どれを使おうか調べたいのに古い情報を参考に判断するのは嫌だよね。

rrdtool tune 

rrdtoolでは、rrdtoolのcreateコマンドを使用してrrdデータベースファイルを作成する。
rrdデータベースファイル作成時にデータソースの正常値範囲など、データベースパラメータを指定する。(ちゃんと作成しておけば)通常はこのパラメータを変更する必要はないのだが、後でパラメータを変更したくなることもある。

こうした時に使用するのがrrdtooのtuneコマンドだ。

rrdtool tune FILENAME.rrd --maximum DS-NAME:MAX

FILENAME.rrd rrdデータベースファイル
DS-NAME データソース名
MAX データソースの取りうる最大値

こんな感じでrrdデータベースパラメータを変更できる。詳細はrrdtoolのtuneコマンドのマニュアルを参照。

でも、必ずしも最初に全てを正しく決めることが出来るわけじゃないし、そもそも後で変更できないより出来た方が良いに決まっているよね。rrdtoolは良くできているツールだよ。

SNMPの一般トラップ 

SNMPの一般トラップ

trap番号OID意味 data binding
0 1.3.6.1.6.3.1.1.5.1 coldStart なし
1 1.3.6.1.6.3.1.1.5.2 warmStart なし
2 1.3.6.1.6.3.1.1.5.3 linkDown ifIndex
SNMPv2以降はifAdminStatusとifOperStatusが追加。
3 1.3.6.1.6.3.1.1.5.4 linkUp ifIndex
SNMPv2以降はifAdminStatusとifOperStatusが追加。
4 1.3.6.1.6.3.1.1.5.5 authenticationFailure
認証失敗
なし
5 1.3.6.1.6.3.1.1.5.6 epgNeighborLoss
EPG失敗
epgNeighAddr
6 1.3.6.1.4.1.エンタープライズ番号.固有トラップ番号 ベンダ固有トラップ ベンダ定義


トラップはsnmptrapdで受信できる。snmptrapdがトラップを受信した際に呼び出すスクリプトは/etc/snmp/snmptrapd.confのtranphandle業で指定する。

traphandle default /path/to/traphandle.pl

トラップを受信したsnmptrapdは、traphandleで指定したスクリプトの標準入力に対してトラップ情報を出力する。スクリプト側では標準入力から読み込んで動作すればよい。
snmptrapdが出力するのはこんな感じ。

router01
UDP: [192.168.1.1]:60201
.1.3.6.1.2.1.1.3.0 31:18:27:02.00
.1.3.6.1.6.3.1.1.4.1.0 .1.3.6.1.6.3.1.1.5.3
.1.3.6.1.2.1.2.2.1.1.3 3
.1.3.6.1.2.1.2.2.1.7.3 2
.1.3.6.1.2.1.2.2.1.8.3 3

1行目 送信元DNS名
2行目 トラップの送信プロトコル、送信元IPアドレス、送信元ポート番号
3行目 トラップ送信元のuptime
4行目 一般トラップOIDとベンダ固有トラップOID
5行目以降 varbind

SNMPトラップの送信


指示子説明使い方
i
INTEGER。整数
 
u
UNSIGNED。符号なし整数
 
c
COUNTER32。32bitカウンタ。
 
s
STRING。文字列。
 
x
HEX STRING。16進数文字列。
 
d
DECIMAL STRING。10進数文字列。
 
n
NULLOBJ。値のないオブジェクト?
 
o
OBJID。OID。
 
t
TIMETICKS。時刻。単位とかは?
 
a
IPADDRESS。IPアドレス。
 
b
BITS。2進数? ビットのバイナリ表現? 具体的にはどんなだ? コマンドでの指定方法とか?
 


コマンドsnmptrapでのトラップ送信例
SNMPv1の場合

snmptrap -v 1 -c COMMUNITY localhost 1.3.6.1.6.3.1.1.5.4 127.0.0.1 3 0 "" .1.3.6.1.2.1.2.2.1.1.0 i 1

SNMPv2の場合

snmptrap -v 2c -c COMMUNITY localhost "" .1.3.6.1.6.3.1.1.5.4 .1.3.6.1.2.1.2.2.1.1.0 i 1

SNMPトラップ OIDメモ 

SNMPトラップのOIDメモ

uptime
DISMAN-EVENT-MIB::sysUpTimeInstance
.1.3.6.1.2.1.1.3.0

トラップ送信元IPアドレス
SNMP-COMMUNITY-MIB::snmpTrapAddress.0
.1.3.6.1.6.3.18.1.3.0

トラップコミュニティ
SNMP-COMMUNITY-MIB::snmpTrapCommunity.0
.1.3.6.1.6.3.18.1.4.0

Net::SNMP 

Net::SNMPってIPv6に対応してる!
素敵

SNMPトラップ 

送信
snmptrapを用いる。

snmptrap -v 1 [COMMON OPTIONS] [-Ci] enterprise-oid agent generic-trap specific-trap uptime [OIDTYPE VALUE]...
snmptrap -v [2c|3] [COMMON OPTIONS] [-Ci] uptime trap-oid [OID TYPE VALUE]...
snmpinform -v [2c|3] [COMMON OPTIONS] uptime trap-oid [OID TYPE VALUE]...


SNMPv1トラップを投げる。

snmptrap -v 1 [COMMON_OPTIONS] [-Ci] enterprise-oid agent generic-trap specific-trap uptime [OID TYPE VALUE]...

enterprise-oid, agent, uptimeに空文字列を指定した場合にはデフォルト値として1.3.6.1.4.1.3.1.1(enterprises.cmu.1.1)、自ホスト名、自ホストのuptimeが用いられる。

TYPEの書式

i INTEGER(整数)
u UNSIGNED(符号なし整数)
c COUNTER32(32bitカウンタ)
s STRING(文字列)
x HEX STRING(16進数文字列)
d DECIMAL STRING(10進数)
n NULLOBJ(nullオブジェクト)
o OBJID(オブジェクトID)
t TIMETICKS
a IPADDRESS(IPアドレス)
b BITS

SNMPトラップの送信と受信 

SNMPトラップの送信と受信

受信
snmptrapdを用いる。

snmptrapdの設定
/usr/share/snmp/snmptrapd.confで設定する。

traphandle {OID|default} PROGRAM [ARG]

  OIDにマッチするトラップを受信した際に起動するプログラムの指定
  OIDの代わりに文字列defaultを指定した場合にはいずれのtraphandleにもマッチしなかった場合にそれが適用される。
  PROGRAMはトラップ詳細を標準入力から受け取る。

  標準入力から受け取るトラップ詳細の書式は次の通り。
    HOSTNAME  送信元ホスト名。gethostbyname()でIPを名前解決して決定。
    IPADDRESS  送信元IPアドレス。
    VARBINDS   トラップとその変数を含むvariable bindingsのリスト。1番目はsystem.sysUpTime.0、2番目は...snmpTrap.snmpTrapOID.0にすべきである。以降はtrapに含まれるvariable bindingsである。
              SNMPv1では最後は...snmpTrap.snmpTrapEnterpriseとその値である。
              SNMPv1トラップは適切な方法でSNMPv2トラップのPDUタイプへ変換される。

createUser username (MD5|SHA) authpassphrase [DES]
  SNMPv3 ユーザーの作成?

format1 format
  SNMPv1 TRAPメッセージを表示するときに使うフォーマット。使用可能なレイアウト文字はsnmptrapd(8)参照。

format2 format
  SNMPv2 TRAP2メッセージとSNMPv2 INFORMメッセージを表示するときに使うフォーマット(SNMPv3はSNMPv2形式のTRAPとINFORMを使っている点に注意)。


net-snmp-5.3.1-19.el5_1.2のsnmptrapdはtraphandleコマンドを実行するとブロックしてしまう。このため呼び出されるコマンドは短時間で終了しなければ後から来た他のトラップを取りこぼす事になるかもしれない? それともソケットが受け取って置いてくれるから取りこぼしはしないが処理するのが遅れるのか? →どなたか教えて頂けませんか?

snmptrapdの起動

/etc/init.d/snmptrapd start

psを取ると引数として-Lsdと-p /var/run/snmptrapd.pidがついていた。

-Lsd      man snmpcmdによればログの出力先をsyslogのファシリティDAEMONとする指定。
-p PIDFILE  PIDファイルのパス指定。
-n       送信元IPアドレスを名前解決しない。

※注意:Cent5.0の場合、man snmptrapdで表示される日本語のman pageの内容が古くて役に立たない模様。英語版を参照の事。
・場合によってはファシリティDAEMONは大量のログ出力が行われるので、-Ls[0-7]としてファシリティLOCAL0~7へ変更した方が便利かもしれない。またトラップを沢山受け付けなければならない場合には、syslogdによる負荷を軽減するために/etc/syslogd.confで出力先指定の先頭に'-'を付ける事も検討した方がよいだろう。
・MIBファイル保存場所  /usr/share/snmp/mibs/ (おそらく) snmptrapdの引数-M DIRLISTでも制御可能な模様。