緣起
一直以來都會用 Smokeping 來監視各個機房的對外網路狀況,但 Smokeping 全由 perl 寫成,在某次大搬風之後遺失了設定,所以只能暫時跑著 CGI mode。但是剛剛實在是太誇張的慢了,等到 proxy 一直 timeout ,所以就決定還是來把乖乖設定好吧。
說來也有趣,當時的變動是把 lighttpd 換成 nginx,但不知道什麼原因,當時竟然為了要跑 smokeping 所以必須要借助 lighttpd 去跑 FastCGI 所以把 lighttpd 跑在 127.0.0.0:8080 然後用 nginx proxy 到 lighttpd,然後又好像 smokeping 的 FastCGI 哪裡沒設定好不會動,所以又只好變成了 在 lighttpd 上面跑 CGI mode (真的是脫褲子放屁加吃飽了撐著)
作法
大概看到有幾種方法讓 nginx 直接透過 FastCGI 處理 smokeping :
1) 用 p5-CGI-SpeedyCGI (參考
1)
2) 用 p5-Plack 透過 PSGI 來跑 perl-FastCGI (
參考)
3) 用 p5-FCGI 和 p5-FCGI-ProcManager 來跑 perl-FastCGI (
參考)
這邊是挑 2、3 來測,但 3 比較簡單一點也完工了,步驟大概是這樣:
1) 安裝需要的套件
cd /usr/ports/www/p5-FCGI && make install clean
cd /usr/ports/www/p5-FCGI-ProcManager && make install clean
cd /usr/ports/www/spawn-fcgi && make install clean
或是用 pkg :
pkg install p5-FCGI p5-FCGI-ProcManager spawn-fcgi
2) 編輯 smokeping 的 fastcgi wrapper,vim /usr/local/smokeping/htdocs/smokeping.fcgi 檔案如下:
# -*-perl-*-
use FCGI;
use FCGI::ProcManager;
use lib qw(/usr/local/smokeping/lib);
use Smokeping 2.004002 ;
use CGI::Fast;
my $cfg = "/usr/local/etc/smokeping/config";
my $proc_manager = FCGI::ProcManager->new( {n_processes => 5} );
my $request = FCGI::Request();
$proc_manager->pm_manage();
while (my $q = new CGI::Fast) {
Smokeping::cgi($cfg,$q);
}
while($request->Accept() >= 0) {
my $q = new CGI::Fast;
$proc_manager->pm_pre_dispatch();
Smokeping::cgi($cfg,$q);
$proc_manager->pm_post_dispatch();
exit(0);
}
3) 編輯啟動 fastcgi 的 script, vim /usr/local/smokeping/htdocs/spawn-smoke 檔案如下:
#!/bin/sh
/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 你要的PORT\
-P /var/run/smokeping-fastcgi.pid -u www \
-f /usr/local/smokeping/htdocs/smokeping.fcgi
4) 修改 nginx.conf ,增加 smokeping 的設定
location /smokeping/smokeping.cgi {
error_log /PATH_TO/smoke-error.log info;
access_log /PATH_TO/smoke-access.log combined;
fastcgi_pass 127.0.0.1:你要的PORT;
fastcgi_param SCRIPT_FILENAME /usr/local/smokeping/htdocs$fastcgi_script_name;
include fastcgi_params;
}
location /smokeping/ {
error_log /PATH_TO/smoke-error.log info;
access_log /PATH_TO/smoke-access.log combined;
alias /usr/local/smokeping/htdocs/;
}
然後記得跑
/usr/local/smokeping/htdocs/spawn-smoke
之後再把 nginx 跑起來就沒問題了。
UPDATE:
要自動啟動的話 改 rc.conf
spawn_fcgi_enable="YES"
spawn_fcgi_app="/usr/local/smokeping/htdocs/smokeping.fcgi"
spawn_fcgi_bindaddr="127.0.0.1"
spawn_fcgi_bindport="PORT"
Update: slave 設定
smokeping_enable="YES"
smokeping_flags="--master-url=http://MASTER.cgi --slave-name=SLAVENAME --cache-dir=/var/run/smokeping --shared-secret=SECRET"
另外,如果要讓機器自動跑起來的話,我是直接偷改 /usr/local/etc/rc.d/smokeping :
# Define these smokeping_* variables in one of these files:
# /etc/rc.conf
# /etc/rc.conf.local
# /etc/rc.conf.d/smokeping
#
# DO NOT CHANGE THESE DEFAULT VALUES HERE
#
# smokeping_flags=""
smokeping_enable=${smokeping_enable-"NO"}
smokeping_pidfile=${smokeping_pidfile-"/usr/local/var/smokeping/smokeping.pid"}
smokeping_fcgi_pidfile=${smokeping_fcgi_pidfile-"/var/run/smokeping-fastcgi.pid"}
smokeping_logfile=${smokeping_logfile-"/var/log/smokeping.log"}
smokeping_user=${smokeping_user-"smokeping"}
smokeping_group=${smokeping_group-"smokeping"}
. /etc/rc.subr
name="smokeping"
rcvar="smokeping_enable"
load_rc_config $name
command="/usr/local/bin/smokeping"
command_args="--logfile=${smokeping_logfile}"
pidfile="${smokeping_pidfile}"
fcgi_pidfile="${smokeping_fcgi_pidfile}"
extra_commands="reload"
reload_cmd="smokeping_reloadcmd"
start_precmd="smokeping_startprecmd"
stop_cmd="smokeping_stopcmd"
status_cmd="smokeping_statuscmd"
spawn_smokeping_fcgi="/usr/local/smokeping/htdocs/spawn-smoke"
smokeping_reloadcmd()
{
$command --reload
}
smokeping_statuscmd()
{
if [ ! -e $pidfile ];
then
echo "pidfile does not exist. $name is not running?";
exit 1;
fi
if pgrep -F $pidfile >/dev/null;
then
echo "$name is running.";
else
echo "$name is not running.";
exit 1;
fi
}
smokeping_stopcmd()
{
if pgrep -F $pidfile >/dev/null;
then
kill $sig_stop `cat $pidfile`;
wait_for_pids `cat $pidfile`;
kill $sig_stop `cat $fcgi_pidfile`;
wait_for_pids `cat $fcgi_pidfile`;
rm -rf $fcgi_pidfile;
else
echo "$name is not running.";
exit 1;
fi
}
smokeping_startprecmd()
{
if [ ! -e $smokeping_logfile ];
then
install -o smokeping -g smokeping /dev/null $smokeping_logfile || echo "ERROR: Could not initialize logfile at $smokeping_logfile.";
fi
if [ ! -e $fcgi_pidfile ];
then
$spawn_smokeping_fcgi;
echo "starting smokeping fastcgi";
fi
}