Apache の具合を Munin で可視化しよう

表題の通りでございます。munin-node のプラグインに apache_accesses, apache_processes, apache_volume というのがあるので、これを使ってみましょう。

上記プラグインは apache の mod_status というモジュールの server-status というハンドラ (apache 専用の web アプリ) に頼ってます。Slackware 14.1 なら最初からこのモジュールがロードされてます。/etc/httpd/httpd.conf の以下の行をアンコメントしましょう。

Include /etc/httpd/extra/httpd-info.conf

/etc/httpd/extra/httpd-info.conf の以下の行をアンコメントしましょう。

ExtendedStatus On

終わったら apache をリロードします。

sudo /usr/sbin/apachectl configtest && sudo /usr/sbin/apachectl graceful

http://localhost/server-status にアクセスすると、色々表示されます。

curl http://localhost/server-status

munin-node-configure を動かしてみましょう。

sudo /usr/local/munin/sbin/munin-node-configure --suggest

足りない perl モジュールがあるようです。

#中略
apache_accesses            | no   | no [LWP::UserAgent not found]
apache_processes           | no   | no [LWP::UserAgent not found]
apache_volume              | no   | no [LWP::UserAgent not found]
#後略

cpan でインストールしましょう。

# メモリ浪費対策です。 ~/.profile にでも書いときましょう。
ulimit -d $((256*1024*1024))
sudo cpan install LWP::UserAgent

munin-node-configure を再度実行すると、今度は apache 用のプラグインが利用可能と判断されます。

プラグインを有効にします。

sudo /usr/local/munin/sbin/munin-node-configure --suggest --shell | sudo bash
sudo /etc/rc.d/rc.munin-node restart

数十分待ってデータが溜まったら、munin の画面をチェックしてみましょう。apache という項目があるはずです。

グラフ化される項目は、毎秒のアクセス数 (ポート別)、サブプロセスの状況 (ビジー、アイドル、フリー)、転送量です。プロセスの状況を見て MPM の設定を変更したり、転送量の状況を見て回線の増強 (共有回線を上位プランに変更したり、専用回線を導入したり) を検討したり、アクセス数を見て一喜一憂したり、という感じでしょうか。

(コウヅ)

ファイルをバックアップしよう

ハードディスクはかなり壊れやすい装置です (SSD はどうだか知りません…)。なので、ファイルというかディスク全体のバックアップを取っとかないと、恐ろしいことになります。ということで、 Slackware マシンのディスクを外付けディスクにバックアップしましょう、という想定です。

バックアップソリューションは色々ありますが、マシン単体のバックアップをするなら、dump か rsnapshot でしょうか。

dump は Linux 標準のバックアップシステムといっていい代物です。ファイルシステム全体のイメージをダンプします。リストアには専用の restore コマンドを使います。何故か Slackware 14.1 には dump コマンドが入っておらず、SlackBuilds に頼らないといけません。あんまり使ったこともないし、ダンプしたイメージが破損してたという素敵な思い出もあります。

rsnapshot は rsync を使ったバックアップシステムです。Mac OS X の Time Machine みたいなものです。これはただのファイルコピーなので、特定のファイルだけを復旧したい、という時も迅速に対応できます。外付けのディスクだけでなく、リ モートホストに/リモートホストからバックアップすることもできます (dump にも rdump というのがあります)。

ということで、rsnapshot をインストールしましょう。SlackBuilds.org からパッケージをダウンロードします。http://slackbuilds.org/repository/14.1/misc/rsnapshot/. ビルドのやり方はソースコードをらくらくコンパイルを参考にしてください。

インストールが終わったら、/etc/rsnapshot.conf を編集します。

cd /etc
# オリジナルファイルをコピーしておきます
sudo cp rsnapshot.conf rsnapshot.conf.default
sudo vim rsnapshot.conf

血迷って日本語訳しました。小一時間かかったので、誰かの役に立てば良いんですが。微妙に設定がデフォルトと違うので注意してください。

#################################################
# rsnapshot.conf - rsnapshot の設定ファイル     #
#################################################
#                                               #
# 以下のルールに注意してください:              #
#                                               #
# このファイルは要素間にタブが必要です          #
#                                               #
# ディレクトリ名の末尾にスラッシュが必要です:  #
#   正解 : /home/                              #
#   不正解: /home                               #
#                                               #
#################################################

###############################
# CONFIG ファイルのバージョン #
###############################

config_version  1.2

#################################
# SNAPSHOT のルートディレクトリ #
#################################

# 全てのスナップショットはこのルートディレクトリ以下に保存されます。
#
snapshot_root   /.snapshots/

# no_create_root が有効だと、rsnapshot はsnapshot_root ディレクトリを自動
# 的には作成しません。これは FireWire や USB 等のリムーバブルメディアに
# バックアップする時に特に便利です。
#
#no_create_root 1

#################################
# 外部プログラムとの依存関係    #
#################################

# LINUX ユーザー: "cmd_cp" をアンコメントして下さい。追加機能が利用可能になり
#                 ます。
# それ以外の人:   互換性のため、"cmd_cp" をコメントアウトしたままにして下さい。
#
# 詳細は README ファイルか man ページを見て下さい。
#
cmd_cp          /usr/bin/cp

# 内蔵の perl ルーチンの代わりに rm プログラムを使うには、これをアンコメント
# して下さい。
#
cmd_rm          /usr/bin/rm

# 何をするにも rsync は必須です。これが唯一の必須コマンドです。
#
cmd_rsync       /usr/bin/rsync

# rsync を使ってリモートに ssh でバックアップするには、これをアンコメント
# して下さい。
#
#cmd_ssh        /usr/bin/ssh

# syslog サポートを無効にするには、これをコメントアウトして下さい。
#
cmd_logger      /usr/bin/logger

# ディスク使用状況の確認に使う "du" へのパスを指定するには、これをアン
# コメントして下さい。古いバージョンの "du" を使う場合、下の "du_args" 
# パラメータも確認した方がいいかも知れません。
#
cmd_du          /usr/bin/du

# rsnapshot-diff へのパスを指定するには、これをアンコメントして下さい。
#
cmd_rsnapshot_diff      /usr/bin/rsnapshot-diff

# rsnapshot がファイルを同期する直前に実行するスクリプト (および
# オプションの引数) へのパスを指定子て下さい。
#
#cmd_preexec    /path/to/preexec/script

# rsnapshot がファイルを同期した直後に実行するスクリプト (および
# オプションの引数) へのパスを指定子て下さい。
#
#cmd_postexec   /path/to/postexec/script

#########################################
#           バックアップ間隔            #
# ユニークかつ昇順でなければなりません  #
# つまり、hourly, daily, weekly 等々。  #
#########################################

#interval       hourly  6
interval        daily   7
interval        weekly  4
#interval       monthly 3

#################################################
#             グローバルオプション              #
# 全てオプション。適切なデフォルト値を持ちます。#
#################################################

# 冗長さの度合い、 1 から 5.
# 1     静か            致命的エラーのみ
# 2     デフォルト      エラーと警告のみ
# 3     冗長            実行されたシェルコマンドを表示
# 4     更に冗長        より冗長な情報を表示
# 5     デバッグモード  全て
#
verbose         2

# 上の "verbose" と同じですが、これを使うとログファイルに送られるデータ
# の量を制御できます。デフォルトは 3 です。
#
loglevel        3

# これを有効にすると、指定したファイルにデータが書き込まれます。書かれる
# データの量は "loglevel" パラメータで制御します。
#
logfile /var/log/rsnapshot

# 有効にすると、2つのインスタンスが同時に実行する (そして snapshot_root を
# めちゃくちゃにする) ことを防ぐためのロックファイルを書き込みます。
# 有効にする場合、ロックファイルディレクトリを無関係なユーザーからは書き
# 込みできないようにして下さい。さもないと、プログラムの実行を邪魔すること
# が可能になってしまいます。
#
lockfile        /var/run/rsnapshot.pid

# デフォルトの rsync 引数。全ての rsync コマンドは最低でもこれらの
# オプションがセットされます。
#
#rsync_short_args       -a
#rsync_long_args        --delete --numeric-ids --relative --delete-excluded

# デフォルトでは ssh に渡される引数はありませんが、ここで指定することが
# できます。
#
#ssh_args       -p 22

# "du" プログラム (ディスク使用状況の報告) のデフォルトの引数。GNU 版の "du"
# が望ましいです。詳細は man ページを見て下さい。もし利用中の "du" が -h
# フラグに非対応の場合は、-k フラグを試して下さい。
#
#du_args        -csh

# 有効にすると、rsync がバックアップポイント内でファイルシステムの
# パーティションをまたがなくなります。これは rsync に -x オプションを渡すと
# いうことです。
# デフォルトは 0 (オフ) です。
#
one_fs          1

# include と exclude パラメータは rsync に直接渡されます。複数の include/
# exclude パラメータを使う場合、それぞれで行を分けて下さい。ファイル名の
# パターンの指定方法については rsync の man ページの --include と --exclude
# オプションを見て下さい。
#
# 
exclude /.snapshots/
#include        ???
#include        ???
#exclude        ???
#exclude        ???

# include_file と exclude_file パラメータは rsync に直接渡されます。詳細は
# rsync の man ページの --include-from と --exclude-from オプションを見て
# 下さい。
#
#include_file   /path/to/include/file
#exclude_file   /path/to/exclude/file

# 使用する rsync が --link-dest に対応しているなら、これを有効にしても良い
# でしょう。これが特殊ファイル (FIFO 等) をクロスプラットフォームでサポート
# する最善の方法です。
# デフォルトは 0 (off) です。
#
link_dest       1

# sync_first を有効にすると、rsnapshot のデフォルトの挙動が変わります。通常、
# rsnapshot が最短の間隔 (つまり "rsnapshot hourly") で呼び出されると、
# ファイルを同期「してから」ローテートします。sync_first を有効にすると、
# "rsnapshot sync" がファイルの同期を行った後、全てのインターバルがファイル
# のローテートを呼び出します。詳細は man ページを見て下さい。デフォルトは
# 0 (オフ) です。
#
sync_first      0

# 有効にすると、rsnapshot は各インターバルの一番古いディレクトリを
# [interval_name].delete に移動し、終了間際にロックファイルとその
# ディレクトリを削除します。デフォルトは 0 (オフ) です。
#
#use_lazy_deletes       0

# rsync のリトライ回数。ネットワークの問題や、例えば、ssh で
# "Corrupted MAC on input" エラーを起こすようなネットワークカードの
# 問題を経験した場合、これを非ゼロの値に設定して rsync を再実行させて
# 下さい。
#
#rsync_numtries 0

########################################
### バックアップポイントとスクリプト ###
########################################

# LOCALHOST
backup  /       localhost/
backup  /boot   localhost/
#backup /home/          localhost/
#backup /etc/           localhost/
#backup /usr/local/     localhost/
#backup /var/log/rsnapshot              localhost/
#backup /etc/passwd     localhost/
#backup /home/foo/My Documents/         localhost/
#backup /foo/bar/       localhost/      one_fs=1, rsync_short_args=-urltvpog
#backup_script  /usr/local/bin/backup_pgsql.sh  localhost/postgres/

# EXAMPLE.COM
#backup_script  /bin/date "+ backup of example.com started at %c"       unused1
#backup root@example.com:/home/ example.com/    +rsync_long_args=--bwlimit=16,exclude=core
#backup root@example.com:/etc/  example.com/    exclude=mtab,exclude=core
#backup_script  ssh root@example.com "mysqldump -A > /var/db/dump/mysql.sql" unused2
#backup root@example.com:/var/db/dump/  example.com/
#backup_script  /bin/date       "+ backup of example.com ended at %c"   unused9

# CVS.SOURCEFORGE.NET
#backup_script  /usr/local/bin/backup_rsnapshot_cvsroot.sh      rsnapshot.cvs.sourceforge.net/

# RSYNC.SAMBA.ORG
#backup rsync://rsync.samba.org/rsyncftp/       rsync.samba.org/rsyncftp/

上のコンフィグですが、/ と /boot の2つのパーティションを /.snapshots にバックアップします。実用する時は /.snapshots に外部のディスクのマウントしておいて下さい。今回はただのテストなので、外部ディスクを使いません (バックアップ元と先のディスクが同じ)。なので、 /.snapshots ディレクトリのバックアップを取らないように exclude で除外してます。日別バックアップを7個まで、週別バックアップを4個まで保存します。バックアップ先のディスクの容量の様子を見ながら調節しましょう。

コンフィグファイルを作ったらテストします。

rsnapshot -t daily
# 実行結果
#echo 32595 > /var/run/rsnapshot.pid 
#mkdir -m 0700 -p /.snapshots/

-t はテストの t です。

実際にバックアップを取るには、以下のように cron ジョブを設定します。

0 2 * * * root rsnapshot daily
0 4 * * 0 root rsnapshot weekly

上の rsnapshot.conf でログファイルを書くように設定したので、logrotate で定期的にローテートさせます。

/var/log/rsnapshot {
        notifempty
        weekly
}

すると、こういう感じに日々バックアップが作成されます。

sudo find /.snapshots -maxdepth 2
# 実行結果
#/.snapshots
#/.snapshots/daily.0
#/.snapshots/daily.0/localhost</pre>
daily.0/localhost 内に / の内容がコピーされるわけですが、各バックアップで全く同じ内容のファイルはハードリンクしてくれるので、ディスク容量はそれほど食わない…はずです。

(コウヅ)

MySQL のバックアップを取ろう

昨今の web アプリは MySQL だの PostgreSQL だのといったデータベースサーバーを平気で使います。なので DB が吹っ飛んだら一巻の終わり、バッドエンドです。

ということで、DB がグシャッと壊れても復旧できるように、日々ダンプしましょう。なんと、この作業に logrotate を使うことができます。

/etc/logrotate.d/mysql に以下の内容を追記します。

/var/dumps/mysql.sql.xz {
  rotate 14
  daily
  nocompress
  nocopytruncate
  postrotate
    HOME=/root mysqldump --opt --all-databases | xz &gt; /var/dumps/mysql.sql.xz
  endscript
}

続いてダミーの mysql.sql.xz を作ります。

sudo touch /var/dumps/mysql.sql.xz

なお、上記内容は http://en.wikibooks.org/wiki/MySQL/Administration#Daily_rotated_mysqldump_with_logrotate にある例をちょっといじっただけのものです。

(コウヅ)

リソース使用状況をグラフにしよう

munin-node-view

munin-dynazoom

サーバーのメモリや CPU の使用率、ディスクの空き容量、apache の接続数、キューに溜まっているメールの数等を Munin を使ってグラフに出力してみましょう。問題点が浮き彫りになるかも?なお、Munin のインストールは結構骨が折れるので、覚悟して下さい。

Munin はクライアントサーバー型のソフトウェアですが、今回はサーバーとクライアントの両方を同じ slackware マシンにインストールします。公式サイトから 2.0.19 をダウンロードします。

Munin のインストールの前に、 rrdtools を SlackBuilds でインストールします。Munin の動作に必要なものです。SlackBuilds の使い方はソースコードをらくらくコンパイルを参考にしてください。Slackware 14.1 用の rrdtools パッケージ:http://slackbuilds.org/repository/14.1/libraries/rrdtool/

パッケージを展開したら、中にある Makefile.config を編集します (詳細なインストール方法は INTALL に書いてあります)。今回は以下のように /usr/local/munin 以下にインストールしてみました。

--- Makefile.config.orig   2014-01-14 16:08:15.291355171 +0900
+++ Makefile.config     2014-01-14 16:11:47.538355171 +0900
@@ -17,10 +17,10 @@
 #
 # the base of the Munin installation.
 #
-PREFIX     = $(DESTDIR)/opt/munin
+PREFIX     = $(DESTDIR)/usr/local/munin

 # Where Munin keeps its configurations (server.conf, client.conf, ++)
-CONFDIR    = $(DESTDIR)/etc/opt/munin
+CONFDIR    = $(PREFIX)/etc

 # Server only - where to put munin-cron
 BINDIR     = $(PREFIX)/bin
@@ -42,13 +42,13 @@
 CGIDIR     = $(PREFIX)/www/cgi

 # Where to put internal data for master (RRD, internal files, ...)
-DBDIR      = $(DESTDIR)/var/opt/munin
+DBDIR      = $(DESTDIR)/usr/local/munin/db

 # Where to put CGI cached files (for master only)
 CGITMPDIR  = $(DBDIR)/cgi-tmp

 # Where to put internal data for node (plugin state, ...)
-DBDIRNODE  = $(DESTDIR)/var/opt/munin-node
+DBDIRNODE  = $(DESTDIR)/usr/local/munin/munin-node

 # Client only - Where the spool files are written. Must be writable by
 # group "munin", and should be preserved between reboots
@@ -63,7 +63,7 @@

 # Location of PID files and other statefiles. On the server, must be
 # writable by the user "munin".
-STATEDIR   = $(DESTDIR)/var/run/munin
+STATEDIR   = $(DESTDIR)/usr/local/munin/state

 # The perl interpreter to use
 PERL       := $(shell which perl)

munin ユーザーとグループを作成します。

sudo /usr/sbin/useradd -s /sbin/nologin -d /usr/local/munin munin
id munin
# 実行結果
#uid=1001(munin) gid=1001(munin) groups=1001(munin)

-s /sbin/nologin を指定することで、そのユーザーはログインできなくなります。-d /usr/local/munin でホームディレクトリを指定しています。何も指定しないと /home/munin という存在しないディレクトリが設定されてしまい、munin が正しく動作しないので注意しましょう。

それから make… の前に、必要な Perl モジュールをインストールします。 Munin は Perl で書かれています。必要なモジュールの一覧は INSTALL に載ってます。

初めて cpan (Perl のモジュールを手軽にインストールするための仕組み) を使うので、 cpan シェルを起動してみます。

kozu@slackware-> sudo cpan
パスワード:

CPAN.pm requires configuration, but most of it can be done automatically.
If you answer 'no' below, you will enter an interactive dialog for each
configuration option instead.

Would you like to configure as much as possible automatically? [yes] 

Autoconfigured everything but 'urllist'.

Now you need to choose your CPAN mirror sites.  You can let me
pick mirrors for you, you can select them from a list or you
can enter them by hand.

Would you like me to automatically choose some CPAN mirror
sites for you? (This means connecting to the Internet) [yes] 
Trying to fetch a mirror list from the Internet
Fetching with HTTP::Tiny:
http://www.perl.org/CPAN/MIRRORED.BY

Looking for CPAN mirrors near you (please be patient)
........................ done!

New urllist
  http://cpan.sarang.net/
  http://ftp.kaist.ac.kr/pub/CPAN/
  http://ftp.neowiz.com/CPAN/

Autoconfiguration complete.

commit: wrote '/root/.cpan/CPAN/MyConfig.pm'

You can re-run configuration any time with 'o conf init' in the CPAN shell
Terminal does not support AddHistory.

cpan shell -- CPAN exploration and modules installation (v2.00)
Enter 'h' for help.

変なミラーサイトが選ばれてしまったので、直します。o conf urllist shift でミラーサイトを1つ削除できます。ここでは3回行ってミラーサイトを全て削除しています。それから unshift で新しいミラーサイトを押し込んでいます。o conf commit で設定を保存します。

cpan[7]> o conf urllist shift
Please use 'o conf commit' to make the config permanent!

cpan[8]> o conf urllist shift
Please use 'o conf commit' to make the config permanent!

cpan[9]> o conf urllist shift
Please use 'o conf commit' to make the config permanent!

cpan[10]> o conf urllist unshift http://ftp.nara.wide.ad.jp/pub/CPAN/
Please use 'o conf commit' to make the config permanent!

cpan[11]> o conf urllist unshift http://mirror.jre655.com/CPAN/
Please use 'o conf commit' to make the config permanent!

cpan[12]> o conf commit
commit: wrote '/root/.cpan/CPAN/MyConfig.pm'

cpan[13]> q
Terminal does not support GetHistory.
Lockfile removed.

とりあえず q コマンドで cpan シェルを終了しました。モジュールをもりもりインストールしましょう。途中いくつか質問されることがありますが、全部デフォルト値のままエンターキーを押すだけで十分です。

# メモリ不足で CPAN が異常終了するので、プロセスデータセグメントの最大サイズを設定します。
# slackware 14.1 のデフォルト値は unlimited みたいです。
ulimit -d $((256 * 1024 * 1024))
sudo cpan install Time::HiRes
# 中略
#  /usr/bin/make install  -- OK
# 以下同様です。
sudo cpan install Storable
sudo cpan install Digest::MD5
sudo cpan install HTML::Template
sudo cpan install Text::Balanced
sudo cpan install Params::Validate
sudo cpan install Net::SSLeay
sudo cpan install Getopt::Long
sudo cpan install File::Copy::Recursive
sudo cpan install CGI::Fast
sudo cpan install IO::Socket::INET6
sudo cpan install Log::Log4perl
# IPC::Shareable はテストで失敗します...
sudo cpan install IPC::Shareable
sudo cpan install Log::Dispatch
sudo cpan install MIME::Lite
sudo cpan install Mail::Sender
sudo cpan install Mail::Sendmail

インストールマニュアルには書かれてませんが、以下のモジュールも必要なようです。

sudo cpan install Net::Server
sudo cpan install Net::SNMP
sudo cpan install HTML::Template::Pro
sudo cpan install DBD::SQLite # これは不要かも?
sudo cpan install Date::Manip

Perl モジュールのインストールが終わったら、Munin の Makefile.config のあるディレクトリに移動して make 等を行います。

cd ~/src/munin-2.0.19
make
# Munin のインストール
sudo make install
# Munin ノードとノード用プラグインのインストール
sudo make install-common-prime install-node-prime install-plugins-prime
# Munin 用の cron ジョブのインストール
sudo cp build/resources/linux-cron.d_munin /etc/cron.d/munin
# 所有者の変更
sudo chown -R munin:apache /usr/local/munin
# munin-cgi-html 等がファイルを書き込もうとします
sudo chmod -R g+w /usr/local/munin/{db,www,log}   # www は不要?

Munin サーバーが Munin-node (監視対象) にリソースの使用状況を問い合わせます。グラフ化したい項目ごとにプラグインというものが必要です。デフォルトで様々なプラグインが用意してあり、 munin-node-configure スクリプトを使って使用可能なプラグインを有効にします。

sudo /usr/local/munin/sbin/munin-node-configure  --suggest --shell | sudo bash

Munin-node の起動スクリプトを書きます。

#!/bin/bash

case $1 in
start)
  /usr/local/munin/sbin/munin-node
  rv=$?
  if [ $rv -eq 0 ]; then
    echo "munin-node started"
  else
    echo "start failed"
    exit $rv
  fi
  ;;
stop)
  pkill munin-node
  rv=$?
  if [ $rv -eq 0 ]; then
    echo "munin-node stopped"
  else
    echo "stop failed"
    exit $rv
  fi
  ;;
restart)
  $0 stop && $0 start
  ;;
*)
  echo "usage: $(basename $0) {start|stop}"
  ;;
esac

※ 2014-01-16
ボケてました。pkill munin-node すると rc.munin-node が死んじゃいます…。

--- rc.munin-node~      2014-01-16 21:42:20.265542680 +0900
+++ rc.munin-node       2014-01-16 21:43:49.254542680 +0900
@@ -1,5 +1,7 @@
 #!/bin/bash

+PID=/var/run/munin/munin-node.pid
+
 case $1 in
 start)
   /usr/local/munin/sbin/munin-node
@@ -12,7 +14,7 @@
   fi
   ;;
 stop)
-  pkill munin-node
+  kill $(cat "$PID")
   rv=$?
   if [ $rv -eq 0 ]; then
     echo "munin-node stopped"

上のスクリプトに実行権限を付けて start します。

sudo chmod +x /etc/rc.d/rc.munin-node
sudo /etc/rc.d/rc.munin-node start

munin-node が起動して 4949/tcp をリッスンしてるか確認します。

sudo netstat -tulpn | grep 4949
# 実行結果
#tcp6       0      0 :::4949                 :::*                    LISTEN      20621/perl

telnet で確認します。

telnet localhost 4949
# telnet 接続後の様子です
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
# munin node at slackware.web-press.net
list
cpu df df_inode entropy forks fw_conntrack fw_forwarded_local fw_packets if_err_eth0 if_eth0 interrupts irqstats load memory munin_stats netstat nfs4_client nfs_client nfsd nfsd4 open_files open_inodes postfix_mailqueue proc_pri processes sendmail_mailstats sendmail_mailtraffic swap threads uptime users vmstat
quit
Connection closed by foreign host.

上の方で /etc/cron.d/munin を作成しているので、数十分すると localhost のデータが溜まってきます。

今度は溜まったデータをグラフで見れるように apache を設定します。今ご覧の wordpress が動いているバーチャルホストで munin を見れるように設定します (/munin-cgi/munin-cgi-html/ にアクセスすると Munin の画面が出るようにする)。wordpress の pretty URL 用の RewriteRule がちょっと邪魔なので、ルールを1行追加します。

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# 下の1行を追加
RewriteRule ^munin-cgi - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

slackware.web-press.net のバーチャルホストコンテナに /munin-cgi/munin-cgi-html 等の設定を書き加えます。IP アドレスでアクセス制限してあります (ごめん!)。なお、fast cgi の使用がオススメらしいですが、ここでは普通の cgi として動作させます。

<VirtualHost *:80>
    # 中略
    ScriptAlias /munin-cgi/munin-cgi-graph /usr/local/munin/www/cgi/munin-cgi-graph
    <Location /munin-cgi/munin-cgi-graph>
        Options +ExecCGI
        SetHandler cgi-script
        #Allow from all
        require ip ひ♡み♡つ
    </Location>

    ScriptAlias /munin-cgi/munin-cgi-html /usr/local/munin/www/cgi/munin-cgi-html
    <Location /munin-cgi/munin-cgi-html>
        Options +ExecCGI
        SetHandler cgi-script
        #Allow from all
        require ip ひ♡み♡つ
    </Location>

    Alias /munin-cgi/static /usr/local/munin/etc/static
    <Location /munin-cgi/static>
        require ip ひ♡み♡つ
    </Location>

    # 若干ヤケクソ気味です
    Redirect /munin-cgi/munin-cgi-html/static/dynazoom.html /munin-cgi/static/dynazoom.html
</VirtualHost>

apachectl で文法チェックしてリロードします。

sudo /usr/sbin/apachectl configtest
# 実行結果
#Syntax OK
sudo /usr/sbin/apachectl graceful

Munin の動作設定を cgi 用に変更します。/usr/local/munin/etc/munin.conf を編集します。

--- /usr/local/munin/etc/munin.conf.orig   2014-01-14 19:06:21.500542680 +0900
+++ /usr/local/munin/etc/munin.conf     2014-01-14 19:34:18.271542680 +0900
@@ -5,23 +5,23 @@
 # must be writable by the user running munin-cron.  They are all
 # defaulted to the values you see here.
 #
-#dbdir /usr/local/munin/db
-#htmldir /usr/local/munin/www/docs
-#logdir /usr/local/munin/log/munin
-#rundir  /var/run/munin
+dbdir  /usr/local/munin/db
+htmldir /usr/local/munin/www/docs
+logdir /usr/local/munin/log/munin
+rundir  /var/run/munin

 # Where to look for the HTML templates
 #
-#tmpldir       /usr/local/munin/etc/templates
+tmpldir        /usr/local/munin/etc/templates

 # Where to look for the static www files
 #
-#staticdir /usr/local/munin/etc/static
+staticdir /usr/local/munin/etc/static

 # temporary cgi files are here. note that it has to be writable by 
 # the cgi user (usually nobody or httpd).
 #
-# cgitmpdir /usr/local/munin/db/cgi-tmp
+cgitmpdir /usr/local/munin/db/cgi-tmp

 # (Exactly one) directory to include all files from.
 includedir /usr/local/munin/etc/munin-conf.d
@@ -38,6 +38,7 @@
 # It is single threaded *by design* now.
 #
 #graph_strategy cron
+graph_strategy cgi

 # munin-cgi-graph is invoked by the web server up to very many times at the
 # same time.  This is not optimal since it results in high CPU and memory
@@ -45,11 +46,11 @@
 # 6.  Most likely the optimal number for max_cgi_graph_jobs is the same as
 # max_graph_jobs.
 #
-#munin_cgi_graph_jobs 6
+munin_cgi_graph_jobs 6

 # If the automatic CGI url is wrong for your system override it here:
 #
-#cgiurl_graph /munin-cgi/munin-cgi-graph
+cgiurl_graph /munin-cgi/munin-cgi-graph

 # max_size_x and max_size_y are the max size of images in pixel.
 # Default is 4000. Do not make it too large otherwise RRD might use all
@@ -67,6 +68,7 @@
 # - cgi html has some bugs, mostly you still have to launch munin-html by hand
 # 
 #html_strategy cron
+html_strategy cgi

 # munin-update runs in parallel.
 #

さて、この状態で /munin-cgi/munin-cgi-html/ にアクセスすると、スタイルも何も適用されていないおかしなページが表示されます。正攻法が分からないので、 munin のテンプレートをいじってしまいましょう。テンプレートファイルは /usr/local/munin/etc/templates にあります。 – で始まる行は削除、 + は追加、です。詳細は diff を参照してください。

--- /usr/local/munin/etc/templates/munin-serviceview.tmpl.orig     2014-01-14 19:21:01.166542680 +0900
+++ /usr/local/munin/etc/templates/munin-serviceview.tmpl       2014-01-14 19:21:25.311542680 +0900
@@ -73,7 +73,7 @@
 <tr>
        <th>Field</th>
        <th><span title="For use in munin.conf">Internal name</span></th>
-       <th><a href="<TMPL_VAR ESCAPE="URL" NAME="R_PATH">/static/definitions.html#data_types">Type</a></th>
+       <th><a href="/munin-cgi/static/definitions.html#data_types">Type</a></th>
        <th>Warn</th>
        <th>Crit</th>
        <th>Info</th>
--- /usr/local/munin/etc/templates/partial/head.tmpl.orig  2014-01-14 19:21:30.726542680 +0900
+++ /usr/local/munin/etc/templates/partial/head.tmpl    2014-01-14 19:21:59.716542680 +0900
@@ -3,11 +3,11 @@
           "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <head>
-  <link rel="stylesheet" href="<TMPL_VAR NAME="R_PATH">/static/style-new.css" type="text/css" /> 
+  <link rel="stylesheet" href="/munin-cgi/static/style-new.css" type="text/css" /> 
   <TMPL_IF NAME="SHOW_ZOOM_JS">
-     <script src="<TMPL_VAR NAME="R_PATH">/static/formatdate.js" type="text/javascript" language="javascript"/>
-     <script src="<TMPL_VAR NAME="R_PATH">/static/querystring.js" type="text/javascript" language="javascript"/>
-     <script src="<TMPL_VAR NAME="R_PATH">/static/zoom.js" type="text/javascript" language="javascript"/>
+     <script src="/munin-cgi/static/formatdate.js" type="text/javascript" language="javascript"/>
+     <script src="/munin-cgi/static/querystring.js" type="text/javascript" language="javascript"/>
+     <script src="/munin-cgi/static/zoom.js" type="text/javascript" language="javascript"/>
   </TMPL_IF>
   <TMPL_UNLESS NAME="SHOW_ZOOM_JS">
     <meta http-equiv="refresh" content="300" /> 
@@ -15,7 +15,7 @@
   <title><TMPL_LOOP NAME="PATH"><TMPL_IF NAME="pathname"> :: <TMPL_VAR ESCAPE="HTML" NAME="pathname"><TMPL_ELSE>Munin</TMPL_IF></TMPL_LOOP></title>
   <meta http-equiv="content-type" content="application/xhtml+xml; charset=iso-8859-1" />
   <meta name="author" content="Auto-generated by Munin" />
-  <link rel="icon" type="image/vnd.microsoft.icon" href="<TMPL_VAR NAME="R_PATH">/static/favicon.ico" />
-  <link rel="SHORTCUT ICON" href="<TMPL_VAR NAME="R_PATH">/static/favicon.ico"/>
+  <link rel="icon" type="image/vnd.microsoft.icon" href="/munin-cgi/static/favicon.ico" />
+  <link rel="SHORTCUT ICON" href="/munin-cgi/static/favicon.ico"/>

 </head>

ログローテートも設定しましょう。たぶんこんな感じ。

/usr/local/munin/log/munin/*.log {
        weekly
        missingok
        copytruncate
        notifempty
}

たぶんこれで大体終わりです。監視対象を増やす時は、対象のホストに munin-node とプラグイン一式をインストールし、必要なプラグインを設定し、munin-node を動かしておきます。それから munin サーバーの munin.conf に監視対象の名前とアドレスを書き加えます。

プラグインの設定は munin-node.conf とか plugin-conf.d/hoge とかで行います。プラグイン自体は /usr/local/munin/lib/plugins にあります。pod2text でマニュアルが読めます。

pod2text /usr/local/munin/lib/plugins/postfix_mailqueue | less

今回は wordpress を使ったバーチャルホストと munin を同居させましたが、munin 用にサブドメインとバーチャルホストを作ったほうが良かったかも?

(コウヅ)

セキュリティパッチを適用しよう

脆弱性というものは、発見されては埋められる、ということを日々繰り返しています。脆弱性を放置することは、悪者共に遊び場を提供することに等しく、畢竟、穴埋め作業を行うのはインターネット利用者の義務であります。

Slackware コミュニティもセキュリティパッチをリリースしてます。アナウンスはメーリングリストで行っており、過去ログも閲覧可能です。

試しに openssh パッケージのパッチを適用してみます。http://www.slackware.com/lists/archive/viewer.php?l=slackware-security&y=2013&m=slackware-security.356319

# パッチをダウンロードします
# 最寄りの奈良先端科学技術大学院大学のサイトを使います
wget -P ~/patches 'http://ftp.nara.wide.ad.jp/pub/Linux/slackware/slackware64-14.1/patches/packages/openssh-6.4p1-x86_64-1_slack14.1.txz'
sudo /sbin/upgradepkg ~/patches/openssh-6.4p1-x86_64-1_slack14.1.txz
# 実行結果
#
#+==============================================================================
#| Upgrading openssh-6.3p1-x86_64-1 package using /home/kozu/patches/openssh-6.4p1-x86_64-1_slack14.1.txz
#+==============================================================================
#
#Pre-installing package openssh-6.4p1-x86_64-1_slack14.1...
#
#Removing package /var/log/packages/openssh-6.3p1-x86_64-1-upgraded-2014-01-10,16:14:11...
#  --> Deleting /usr/doc/openssh-6.3p1/CREDITS
#  --> Deleting /usr/doc/openssh-6.3p1/ChangeLog
#  --> Deleting /usr/doc/openssh-6.3p1/INSTALL
#  --> Deleting /usr/doc/openssh-6.3p1/LICENCE
#  --> Deleting /usr/doc/openssh-6.3p1/OVERVIEW
#  --> Deleting /usr/doc/openssh-6.3p1/README
#  --> Deleting /usr/doc/openssh-6.3p1/README.privsep
#  --> Deleting /usr/doc/openssh-6.3p1/TODO
#  --> Deleting empty directory /usr/doc/openssh-6.3p1/
#
#Verifying package openssh-6.4p1-x86_64-1_slack14.1.txz.
#Installing package openssh-6.4p1-x86_64-1_slack14.1.txz:
#PACKAGE DESCRIPTION:
## openssh (Secure Shell daemon and clients)
##
## ssh (Secure Shell) is a program for logging into a remote machine and
## for executing commands on a remote machine.  It is intended to replace
## rlogin and rsh, and provide secure encrypted communications between
## two untrusted hosts over an insecure network.  sshd (SSH Daemon) is
## the daemon program for ssh.  OpenSSH is based on the last free version
## of Tatu Ylonen's SSH, further enhanced and cleaned up by Aaron
## Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt, and
## Dug Song.  It has a homepage at http://www.openssh.com/
##
#Executing install script for openssh-6.4p1-x86_64-1_slack14.1.txz.
#Package openssh-6.4p1-x86_64-1_slack14.1.txz installed.
#
#Package openssh-6.3p1-x86_64-1 upgraded with new package /home/kozu/patches/openssh-6.4p1-x86_64-1_slack14.1.txz.
#

アップデートが終わったら、パッチのアナウンスにある通り、sshd を再起動します。

sudo /etc/rc.d/rc.sshd restart
# 実行結果
#WARNING: killing listener process only.  To kill every sshd process, you must
#         use 'rc.sshd stop'.  'rc.sshd restart' kills only the parent sshd to
#         allow an admin logged in through sshd to use 'rc.sshd restart' without
#         being cut off.  If sshd has been upgraded, new connections will now
#         use the new version, which should be a safe enough approach.

WARNING を読んでみると、「既存のセッションはノータッチ、新たな接続から新バージョンの sshd を使う」と書いてあります。なので、ssh 経由で slackware マシンを操作している場合、今開いている ssh のセッションはそのままにして、新たに ssh で接続して問題ないかチェックしましょう。問題あったら…どうにかして直しとかないと ssh でログインできなくなり、マシンのある場所 (サーバールーム、IDC、あるいは自宅) まで出かけて直すはめに…。

脆弱性情報は常にチェックしておきたいですね!

(コウヅ)

/tmp には noexec オプションをつけよう

Web アプリケーションのセキュリティホールを突いて変なスクリプトを /tmp にアップロードされちゃうことがあります。もしそういうことをされても、 /tmp パーティションに noexec オプションが付いてれば、被害を食い止めることができる…かもしれません。ただし、 Slackware のインストール時に /tmp 専用パーティションを作成してないとこの技は使えません。

で、 noexec オプションて何やねん。man mount 曰く:

noexec
マウントされたファイルシステム上の任意のバイナリの直接実行を禁止する。 (最近になるまで /lib/ld*.so /mnt/binary のようなコマンドを使って、 バイナリを何とか実行することが可能であった。 このトリックは Linux 2.4.25 / 2.6.0 以降では失敗する。)

http://linuxjm.sourceforge.jp/html/util-linux/man8/mount.8.html より抜粋

バイナリと書いてありますが、シバンの付いたスクリプトの直接実行も禁止してくれます。

/etc/fstab の /tmp のレコードのオプションフィールドに noexec を追加しましょう。

# 例です
/dev/sda6        /tmp             ext4        defaults,noexec         1   2

編集し終えたら、/tmp を再マウントします。

sudo mount -o remount /tmp

ちょっと実験してみましょう。こんなシェルスクリプトを用意します。

#!/bin/bash

echo "こんにちは、世界!"

実行権限を付けて実行してみます。

ls -l hoge.sh 
# 実行結果
#-rwxr-xr-x 1 kozu kozu 48  1月  9 17:23 hoge.sh*
/tmp/hoge.sh
# 実行結果
#-bash: /tmp/hoge.sh: 許可がありません
bash /tmp/hoge.sh 
# 実行結果
#こんにちは、世界!

bash /tmp/hoge.sh だと実行できちゃいますが、 bash は /bin にあるので、しょうがないですね。

なお、 /tmp に noexec オプションが付いてると、 SlackBuilds のビルドが失敗します。そういう時は、一時的に exec オプションを付けます。

sudo mount -o remount,exec /tmp

用が済んだら元に戻します。

sudo mount -o remount /tmp

面倒くさいのが難点です。

※ SlackBuilds の一時ファイル保存先は TMP 環境変数で設定できるみたいです。

sudo TMP=~/tmp bash cronie.SlackBuild

出来上がったパッケージはやはり /tmp に書きだされます。

(コウヅ)

cronie をインストールしよう

Slackware の crond は dillon’s cron というバージョンです。設定を変更したら再起動しないといけないようで使いづらいです。ということで、cronie という代替版をインストールしましょう!

インストールには SlackBuilds を利用します。http://slackbuilds.org/repository/14.1/system/cronie/ からパッケージをダウンロードしてね。SlackBuils の使い方はソースコードをらくらくコンパイルを参考にしてください。

SlackBuilds の cronie のページに注意書きがある通り、cronie をインストールする前にデフォルトの dcron (dillon’s cron) をアンインストールしないといけません。英語は苦手なのだわ!という方のために要約を書いときます。

dcron デーモンを停止し、 dcron パッケージを削除します:
# kill $(pgrep crond)
# removepkg dcron
# rm -rf /var/spool/cron

/etc/rc.d/rc.M のこの行を…
/usr/sbin/crond -l notice
次のように変更します:
/usr/sbin/crond 

http://slackbuilds.org/repository/14.1/system/cronie/ を抄訳

cronie をインストールしたら、早速起動しましょう。

sudo /usr/sbin/crond

/var/log/cron を見てエラーが発生してないか確認します。

sudo tail /var/log/cron
# 実行結果
#Jan  9 16:55:20 slackware crond[27371]: (CRON) STARTUP (1.4.11)
#Jan  9 16:55:20 slackware crond[27371]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 45% if used.)
#Jan  9 16:55:20 slackware crond[27371]: (CRON) INFO (@reboot jobs will be run at computer's startup.)

さて、cron はジョブを実行する度に実行結果を root にメールで送ってくれます。が、非常に鬱陶しいので送信しないようにします。以下のような内容の crontab を作ります。

MAILTO=""

詳しい書式は man 5 crontab を参考にしてください。

dcron と違い、 cronie は1分置きに設定の変更をチェックします。変更を検知すると、 /var/log/cron にこんなようなメッセージを出力します。

Jan  9 16:55:01 slackware crond[27285]: (*system*) RELOAD (/etc/crontab)

これでバッチリですね!

(コウヅ)

※ 2014-10-24 “ソースコードをらくらくコンパイル” へのリンクを修正。何故かこの記事は大人気です。