写个同步分发系统(一)

16 Sep 2011 Posted in  dancer

写程序这个事情,其实规划最麻烦。比方我其实并没留意过一个完整的同步分发系统都有哪些功能。权做练手,想到哪些写哪些好了。
最基础的部分:一个提交文件列表的页面,自动分析文件列表然后从源下载文件,中心下载完成后通知边缘节点开始;
其次:文件完整性的校验,同步和分发的进度报表页面,失败报表的重试选择和报警;
再次:系统分用户,不同用户可选节点指定分发,只查看当前用户的报表。
以上。
今天先完成最基础的部分。还是用dancer -a websync创建应用。然后创建views/websync.tt如下:
```html
</head><body> 继续阅读……


lbnamed代码浅读

08 Sep 2011 Posted in  perl

群里听说lbnamed这么个东东,用perl实现的动态DNS服务器。程序包括三个perl模块:Stanford::DNSserver模块、Stanford::DNS模块、LBCD模块;三个perl程序:lbnamed主程序、poller探测程序、slbcd监控程序(这个有C语言的版本)。 继续阅读……


用nginx区分文件大小做出不同响应

25 Aug 2011 Posted in  nginx

昨晚和前21v的同事聊天,说到我离职后一些技术上的更新。其中有个给某大客户(游戏下载类)的特殊需求设计,因为文件大小差距很大——估计是大版本和补丁的区别——又走的是同一个域名,而squid在响应比较大的文件时,尤其是初次下载的时候,性能比较差,所以拆成两组服务器,squid服务于较小的文件,通过pull方式从peer层获取,nginx服务于较大的文件,通过push方式由peer层分发同步。外部发布域名一律解析到squid服务器组上,请求透传到peer层的nginx,nginx分析这个url的content-length,如果大于阈值,则不返回文件,而是302到nginx服务器组的独立域名下的相应url去。 继续阅读……


CloudForecast学习笔记(三)

18 Aug 2011 Posted in  perl

第三篇,看web部分。主程序cloudforecast_web里主要就是调用CloudForecast::Web的run()函数,接下来去看CloudForecast::Web。
照例还是加载配置,然后这里主要多了两个accessor:allowfrom和front_proxy。用来定制acl和代理的。从下文可以看到,分别是采用了Plack::Middleware::Access和Plack::Middleware::ReverseProxy两个模块进行控制。
然后是主要部分,通过Plack::Builder建立$app:
1、初始化:”my $app = $self->psgi;”,这里是调用父层”use Shirahata -base;”的psgi()函数完成的。稍后再看这个。
2、包装:取出前面说的allowfrom和front_proxy部分后,代码如下:
perl $app = builder { enable 'Plack::Middleware::Lint'; enable 'Plack::Middleware::StackTrace'; enable 'Plack::Middleware::Static', path => qr{^/(favicon\.ico$|static/)}, root =>Path::Class::dir($self->root_dir, 'htdocs')->stringify; $app; };
真实加载顺序是倒序的,先加载Static.pm,用来服务静态文件,意即url路径为^/static/.*的,实际documentroot为./htdocs/;然后加载StackTrace.pm,用于开发调试的时候,向标准输出输出错误跟踪信息;最后是Lint.pm,用于检查请求/响应的格式是否正确。
然后是加载运行,使用Plack::Loader运行上面build出来的$app。方法如下:
perl my $loader = Plack::Loader->load( 'Starlet', port => $self->port || 5000, host => $self->host || 0, max_workers => 2, ); $loader->run($app);
主要是两个参数,第一个是用来运行plack的服务器模块名称,常见的有starman/twiggy/corona/perlbal等等,这里写的这个Starlet,是基于HTTP::Server::PSGI模块添加预派生(prefork)/热部署(Server::Starter)/优雅重启等功能的一个服务器模块,原来叫的名字是”Plack::Server::Standalone::Prefork::Server::Starter”(简称PSSPSS)…… 继续阅读……


CloudForecast学习笔记(二)

18 Aug 2011 Posted in  perl

接下来看radar部分,也就是探测主程序cloudforecast_radar,其中主要就是调用CloudForecast::Radar中的run()函数。
首先还是惯例,调用ConfigLoader模块加载配置文件;
然后是%SIG信号的定义,用来之后自动重运行的;
然后一个while true死循环:
1、循环里用select(undef,undef,undef,0.5)实现一个0.5秒的sleep;
2、第一个if语句,用来判断是否是父进程,并使用无阻塞的waitpid($pid,WNOHANG)等待子进程完成——即$kid==-1;
3、第二个if语句,用来强制退出死循环,条件是收到%SIG信号;
4、第三个if语句,确认当前时间超过计划中的执行时间(即离上次执行时间最近的整5分钟点),开始执行探测——采用fork()派生子进程。
5、子进程内容是从之前获取的配置文件内,轮询每一台设备,最终调用run_host()函数执行。
然后又是两个if语句,接在while里的last之后,等待子进程全部完成的。 继续阅读……


CloudForecast学习笔记(一)

17 Aug 2011 Posted in  perl

近三天学习cloudforecast,这是一个日本SA写的分布式监控的perl项目。日本的运维水平和perl水平,都让人羡慕啊……
项目介绍:
http://blog.riywo.com/2011/02/27/043646
demo网址:
http://editnuki.info:5000/
下载地址:
https://github.com/kazeburo/cloudforecast
粗略的看了主要文件,主要是用Class::完成的OO,Plack::MiddleWare::完成的web,Gearman::Worker调用Data::*里的具体模块完成对服务器的监控抓取,然后调用RRDs完成监控数据图像的更新,在启动分布式的情况下,则用Gearman::Client传输监控数据给调用RRDs的worker。 继续阅读……


cdn自主监控(六):数据展示页面

02 Aug 2011 Posted in  monitor

接下来进入我不擅长的页面部分了。规划页面分为side和main,side中提供时间选择框/类型下拉选择框和提交按钮;main中展示最后形成的chart。
时间选择框是用js和css完成的,这个网上有很多,不过要同时支持多浏览器和分钟级别的选项的,目前就发现一个好用的。下载地址如下:http://chenlinux.com/images/uploads/Calendar.zip
然后创建cachemoni/public/cdn.html如下:
```html 继续阅读……


cdn自主监控(五):生成charts图像

01 Aug 2011 Posted in  monitor

上篇完成了xml的输出,这篇开始说charts图像的生成。我们采用fusioncharts的免费版,之前博客有提到另一个amcharts,不过amcharts的免费版会在图像左上角加上自己amcharts.com的广告标识……
从fusioncharts官网下载free版的压缩包,有20MB大,不过其中对我们这个小项目有用的只有MSLine.swf/MSBar2D.swf/fusioncharts.js等。
说明:
1、官网介绍上写了支持perl,不过下载包里只有php/asp/jsp/rails的class,没有perl的。所以还是得采用js的方式;
2、js下有setDataURL和setDataXML两个方法,不过官方强烈建议使用setDataURL方法,这种方法可接受的数据量比setDataXML大很多。
页面html很简单,加如下js代码即可:
javascript</script> <script type="text/javascript"> var myChart = new FusionCharts("/Charts/MSBar2D.swf", "myChartId", "600", "500"); myChart.setDataURL(escape("/xml?begin=***&end=***&type=area")); myChart.render("chartdiv"); </script>
要点在这个escape(),如果URL里带参数的话,必须用escape()转码,不然的话第一个&之后的所有参数都会丢失掉!
在调试中注意到,为了忽略缓存,setDataURL()会在url最后跟上一个随机1-4位数字参数&curr=1234然后再发起请求。
现在就可以访问页面看看了~嗯,可以看到图像中的中文字有问题。这是因为fusioncharts不认utf8的中文,必须输出gbk或者gb2312的xml数据才行。所以需要修改一些dancer的charset配置,把config.yml里的charset: UTF-8改成charset: GBK。然后重新请求,中文就正确显示了。
如下图:
继续阅读……


cdn自主监控(四):输出xml数据

28 Jul 2011 Posted in  monitor

准备使用funsioncharts绘图,其采用xml数据,在绘制line图的时候,就要从mysql里读取数据,并输出成xml格式,相关配置如下:
```perl
package cachemoni;
use Dancer ‘:syntax’;
use Dancer::Plugin::Database;
use POSIX qw(strftime); 继续阅读……


cdn自主监控(三):数据库准备工作

27 Jul 2011 Posted in  monitor

准备两个表,一个存储原始数据,另一个存储每5分钟归总一次的数据。之后根据时间段绘制省份运营商性能图的时候,就直接从汇总表里获取数据;原始表留给详细查询。
数据库准备脚本如下:
```mysqlUSE myops;
CREATE TABLE IF NOT EXISTS cdn_ori_record (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
ip INT(10) NOT NULL DEFAULT ‘0000000000’,
isp ENUM(‘0’,’1’,’2’,’3’,’4’),
area INT(4) NOT NULL DEFAULT ‘0000’,
cur_date TIMESTAMP DEFAULT NOW(),
cdn_time INT(10) NOT NULL DEFAULT ‘0’,
cdn ENUM(‘CHINACACHE’,’DNION’,’FASTWEB’) NOT NULL,
KEY time_key (cur_date)
); 继续阅读……


cdn自主监控(二):快速查找ip对应信息

26 Jul 2011 Posted in  monitor

话接上篇,ip整理出来,然后就是接一个ip地址,快速定位查找到它属于哪个ip段,然后返回具体的省份和运营商。因为之前的ip已经转换成数字,而且是顺序排列的,所以可以采用折半算法(二分法)。perl脚本如下:
```perl#!/usr/bin/perl -w
#my $ip = inet_aton(“$ARGV[0]”);
my $ip = inet_aton(get_test_ip());
my $file = $ARGV[1] || ‘iplist.txt’;
my $length = cat $file | wc -l; 继续阅读……


cdn自主监控(一):整理一个可用范围内的尽可能小的ip库

25 Jul 2011 Posted in  monitor

为了跟第三方监控做对比和作为备用,准备自己通过页面js返回数据做个监控。首先第一步,整理一个足够自己用的ip库。
首先,考虑调用会比较频繁,打算把内容尽可能归并,到省级运营商即可;
其次,未知归并完会有多大的情况下,考虑到qqwry的地区都是中文,打算统一使用电话区号代替地区,运营商也有一位数字代替,ip采用inet-aton网络值代替;这样每条记录的字节数固定,可以方便采用seek和sysread提高读取某条记录的速度。 继续阅读……


perl小测试题(转自CU)

21 Jul 2011 Posted in  perl

原贴地址:http://bbs.chinaunix.net/thread-3563215-1-1.html
flw回帖里有翻译,我试答如下:
1. Perl 5 中变量名开头的那个字符(sigils)有哪几种、分别都有什么含义?
$标量@数组%散列&函数
2. 访问一个数组元素时,用 $items[$index] 和用 @items[$index] 有什么区别?
$是标量,@是数组切片
3. 请问 == 和 eq 之间的区别是什么?
分别是数值和字符的比较
4. 在列表上下文中对一个 hash 求值,会得到什么?
应该是得到一个数组?
5. 如何查看关键字的 Perl 文档?
perldoc -f
6. Perl 5 中的函数和方法有什么不同?
方法是bless后的函数调用?
7. Perl 5 什么时候对一个变量所使用的内存进行回收?
引用计数器清空后?(好像记得是)或者执行完成退出的时候
8. 如何做才能够确保一个变量的缺省作用域是词法作用域?
my local?
9. 如何加载模块并且从中导入符号?
use Module;
符号是啥?
10. 是什么在控制 Perl 如何加载模块?有什么办法可以指定一个目录清单告诉 Perl 从这些地方尝试加载模块?
不知道。
use lib qw();或者perl -I或者export PERL5LIB=
11. 你怎么在 Perl 5 的文档中中查看一条错误信息说明?(加分项:了解如何为所有遇到过的错误信息启用解释)
汗,这个用|less然后/搜索……有好办法么?
12. 试着阐述一下把数组传递给函数的时候会发生什么事。
应该是复制一个数组副本出来,然后赋值到@给函数用?
13. 如何传递多个独立的数组给函数?
分别传递数组引用。
14. 对于调用方来说,return 和 return undef 有什么区别?
return的应该是上一个的结果吧?
15. Where do tests go in a standard CPAN distribution?
module里头都有t/目录可以test吧,然后cpan.org上有志愿者?
16. 拿到一个 CPAN 模块后怎样进行测试?
make test
17. 你用什么命令从 CPAN 上安装新模块?
cpanm Module
18. 为什么要使用 open 函数的三参数形式?
预防文件名带有>等特殊字符串
19. 如何检测(和报告)像 open 这样的系统调用产生的错误?(加分项: 知道如何开启自动检测和报告)
在open的时候接上or die $@;
use autodie;
20. 如何在 Perl 5 中抛出一个异常?
die
21. 如何在 Perl 5 中捕获一个异常?
eval {}
22. 用 for 读文件和用 while 读文件有什么不同吗?
for一次性读入;while一次一行
23. 在 Perl 5 的函数或者方法中,你分别是如何处理参数的?
my $abc = shift;
my ($abc, $def) = @
;
24. my ($value) = @_; 中的小括号有什么用?如果删掉会发生什么?
强制为列表环境;
删掉之后变成标量环境就是@_的元素个数了。
25. new 是 Perl 5 的内置函数或者关键字吗?
不是,模块里要自己写new方法。
26. 你怎么看 Perl 的核心模块的文档?如果是 CPAN 模块的话又该如何看?
perldoc查看,不过核心模块和一般模块方法有区别么?
27. 怎样只访问 hash 的值?
values函数 继续阅读……


mysql_history_monitor

08 Jul 2011 Posted in  monitor

上篇加了bash_history的监控,这篇说mysql_history的监控。不像bash4,mysql自始至终没有提供过syslog的代码,只能自己通过守护进程去实时获取~/.mysql_history的记录了。一个小脚本如下:
```perl#!/usr/bin/perl -w
use POE qw(Wheel::FollowTail);
use Log::Syslog::Fast qw(:all); 继续阅读……


bash_syslog_history

08 Jul 2011 Posted in  monitor

@钚钉钬影 童鞋要试验系统日志收集处理,采用rsyslog+loganalyzer做界面,因为需求有把bash_history也带上,所以采用修改bash源码的方式。最先采用了bash4.2(bash4.2已经带了这个功能,但是默认不开启,删掉哪个/**/就行了),不过因为这个bash4.+跟redhat的network-functions脚本有点小矛盾,重启的时候报个错——虽然改起来也很简单,就是加一个./的事情——不过本着尽量改动少的原则,换回bash3.1。
bash3.1里默认没有记录syslog的代码,所以从bash4.2/bashhist.c里复制有关bash_syslog_history代码段到bash3.1中——注意不是原样复制到bashhist.c,那样不顶用——需要复制到lib/readline/history.c中,如下:
```c
+ #include …… void add_history (string) const char *string; { HIST_ENTRY *temp; 继续阅读……


squid监控+dancer小试验

28 Jun 2011 Posted in  dancer

squid监控之前有一篇关于snmp的内容,不过这次是真要用上了,所以细细挑出来几个做监控。碰巧凯哥更新了一把modern perl的东西,我亦步亦趋,也试试dancer。不过花了两天时间,DBIx::Class::Schema还是没搞出来,最终还是简单的用DBI跳过了……
用的database就是之前nmap试验时生成的数据,有application/channel/intranet等column。
首先安装:
perlcpanm Dancer DBI DBD:mysql Template Dancer::Session::YAML dancer -a cachemoni
然后修改cachemoni/lib/cachemoni.pm如下:
```perl
package cachemoni;
use Dancer ‘:syntax’;
use Dancer::Plugin::Database;
use Net::SNMP;
use Digest::MD5 qw(md5_hex);
our $VERSION = ‘0.1’; 继续阅读……


patch制作和使用

23 Jun 2011 Posted in  linux

做运维几年没用过patch,说来也怪了~~趁着上一篇自己的小改动,熟悉一下这个命令的简单用法。
首先是patch的制作,用diff命令。
bashtar zxvf squid-2.7.STABLE9.tar.gz cp squid-2.7.STABLE9 squid-2.7.STABLE9-old && mv squid-2.7.STABLE9 squid-2.7.STABLE9-new #然后按照上篇的内容修改squid-2.7.STABLE9-new/里的文件 diff -uNr squid-2.7.STABLE9-old squid-2.7.STABLE9-new > squid-snmp.patch
这就完成了,好简单啊~来看看patch文件的内容吧:
cdiff -uNr squid-2.7.STABLE9-old/include/cache_snmp.h squid-2.7.STABLE9-new/include/cache_snmp.h --- squid-2.7.STABLE9-old/include/cache_snmp.h 2006-09-22 10:49:24.000000000 +0800 +++ squid-2.7.STABLE9-new/include/cache_snmp.h 2011-06-23 13:25:04.000000000 +0800 @@ -125,6 +125,7 @@ MESH_PTBL_KEEPAL_S, MESH_PTBL_KEEPAL_R, MESH_PTBL_INDEX, + MESH_PTBL_CONN_OPEN, MESH_PTBL_HOST, MESH_PTBL_END }; diff -uNr squid-2.7.STABLE9-old/src/snmp_agent.c squid-2.7.STABLE9-new/src/snmp_agent.c --- squid-2.7.STABLE9-old/src/snmp_agent.c 2009-06-26 06:58:10.000000000 +0800 +++ squid-2.7.STABLE9-new/src/snmp_agent.c 2011-06-23 13:27:31.000000000 +0800 @@ -264,6 +264,11 @@ index, ASN_INTEGER); break; + case MESH_PTBL_CONN_OPEN: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.conn_open, + ASN_INTEGER); + break; default: *ErrP = SNMP_ERR_NOSUCHNAME; break; diff -uNr squid-2.7.STABLE9-old/src/snmp_core.c squid-2.7.STABLE9-new/src/snmp_core.c --- squid-2.7.STABLE9-old/src/snmp_core.c 2008-05-05 07:23:13.000000000 +0800 +++ squid-2.7.STABLE9-new/src/snmp_core.c 2011-06-23 20:36:54.000000000 +0800 @@ -321,7 +321,7 @@ snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 15), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0)), snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 2), - LEN_SQ_MESH + 2, NULL, NULL, 15, + LEN_SQ_MESH + 2, NULL, NULL, 16, snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 2, 1), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_InstIndex, 0), snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 2, 2), @@ -351,6 +351,8 @@ snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 2, 14), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_InstIndex, 0), snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 2, 15), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_InstIndex, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 2, 16), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_InstIndex, 0))), snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2), LEN_SQ_MESH + 1, NULL, NULL, 1,
制作练完了,再练一次使用:
bashcd squid-2.7.STABLE9-old mv ../squid-snmp.patch . patch -p1 < squid-snmp.patch
-p指定从那层目录开始,因为之前diff的时候顶层目录分别叫old和new,如果在其他地方时候的话,别人的目录肯定不会这么命名的,所以就往里进一层,然后用-p1来patch。
然后more一下那三个文件,确认都修改了~
最后回退patch:
bashpatch -R -p1 < squid-snmp.patch
完成~ 继续阅读……


给squid的snmp增加open_conn输出

22 Jun 2011 Posted in  monitor

做反向代理的squid集群监控,在单机维护时,squidclient mgr:server_list里的OPEN CONNS是经常看的一项数据,不过在开启snmp支持后,在mib里却没有找到相关的数据。还一度怀疑是不是cachePeerKeepAlRecv或者cachePeerKeepSent。今天想起来去src里grep了一把源码,顺利的在squid/src/neighbors.c里看到了OPEN CONNS等数据的来源,如下:
cstatic void dump_peers(StoreEntry * sentry, peer * peers) { peer *e = NULL; …… for (e = peers; e; e = e->next) { …… storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open); …… storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
然后在squid/src/snmp_agent.c里看到了这些数据的snmp输出,如下:
cvariable_list * snmp_meshPtblFn(variable_list * Var, snint * ErrP) { variable_list *Answer = NULL; struct in_addr *laddr; int loop, index = 0; char *cp = NULL; peer *p = NULL; int cnt = 0; …… switch (Var->name[LEN_SQ_MESH + 2]) { case MESH_PTBL_NAME: cp = p->name; Answer = snmp_var_new(Var->name, Var->name_length); …… case MESH_PTBL_KEEPAL_R: Answer = snmp_var_new_integer(Var->name, Var->name_length, p->stats.n_keepalives_recv, SMI_COUNTER32); break; case MESH_PTBL_INDEX: Answer = snmp_var_new_integer(Var->name, Var->name_length, index, ASN_INTEGER); break; default: *ErrP = SNMP_ERR_NOSUCHNAME; break; } return Answer; }
一对比,发现确实没有stats.conn_open输出……
好在这个比较简单,稍微改一下,就能搞出来:
1、修改squid/include/cache_snmp.h如下:
cenum { /* cachePeerTable */ …… MESH_PTBL_CONN_OPEN, /*新增这个*/ MESH_PTBL_HOST, MESH_PTBL_END };
2、修改squid/src/snmp_core.c如下:
c void snmpInit(void) { …… snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 2), /* LEN_SQ_MESH + 2, NULL, NULL, 15,这里改成16,大概在324行,通过原来的MIB知道有15的地方就两个,peer的是后一个 */ LEN_SQ_MESH + 2, NULL, NULL, 16, …… snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 2, 15), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_InstIndex, 0), snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 2, 16), /*新增这个16*/ LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_InstIndex, 0))),
3、修改squid/src/snmp_agent.c如下:
c…… case MESH_PTBL_INDEX: Answer = snmp_var_new_integer(Var->name, Var->name_length, index, ASN_INTEGER); break; /*新增下面这段,case的内容在第1步cache_snmp.h里增加了;stats.conn_open由之前grep的结果得知;INTEGER是数值类型,照抄RTT的即可*/ case MESH_PTBL_CONN_OPEN: Answer = snmp_var_new_integer(Var->name, Var->name_length, p->stats.conn_open, ASN_INTEGER); break;
4、重新编译squid,然后用snmpwalk获取数据观察:
bash[root@naigos myops]# snmpwalk -v 2c -c cacti_china 10.168.168.69 .1.3.6.1.4.1.3495.1.5.1.2 -Cc | tail SNMPv2-SMI::enterprises.3495.1.5.1.2.13.3 = Counter32: 0 SNMPv2-SMI::enterprises.3495.1.5.1.2.14.1 = INTEGER: 1 SNMPv2-SMI::enterprises.3495.1.5.1.2.14.2 = INTEGER: 2 SNMPv2-SMI::enterprises.3495.1.5.1.2.14.3 = INTEGER: 3 SNMPv2-SMI::enterprises.3495.1.5.1.2.15.1 = INTEGER: 3 SNMPv2-SMI::enterprises.3495.1.5.1.2.15.2 = INTEGER: 5 SNMPv2-SMI::enterprises.3495.1.5.1.2.15.3 = INTEGER: 6 SNMPv2-SMI::enterprises.3495.1.5.1.2.16.1 = STRING: "10.168.170.43" SNMPv2-SMI::enterprises.3495.1.5.1.2.16.2 = STRING: "10.168.168.73" SNMPv2-SMI::enterprises.3495.1.5.1.2.16.3 = STRING: "10.168.168.122"
原来的SNMPv2-SMI::enterprises.3495.1.5.1.2.15.1 = STRING: “10.168.170.43”变成了SNMPv2-SMI::enterprises.3495.1.5.1.2.16.1 = STRING: “10.168.170.43”,而SNMPv2-SMI::enterprises.3495.1.5.1.2.15.1 = INTEGER: 3就是需要的open_conn数据了! 继续阅读……


mysql测试小工具mybench试用

14 Jun 2011 Posted in  testing

小型的mysql测试工具,主要有自带的mysqlslap、super-smack和mybench。嗯,我这里的小型的意思是指工具安装过程简单。
mysqlslap的使用方法遍地都是,就不先详细写了。根据个人偏好写写mybench吧,毕竟是perl的。
安装很简单,如下:
bashcpanm DBI DBD::mysql Time::HiRes wget http://jeremy.zawodny.com/mysql/mybench/mybench-1.0.tar.gz tar zxvf mybench-1.0.tar.gz cd mybench-1.0 perl MakeFile.PL && make && make install
但是使用就不是太简单了——mysqlslap会自己生成(-a选项)sql,super-smack则带了一个gen-data程序生成数据然后自动导入,但是mybench没有,所以只能自己搞定数据。
不过mybench还是自己生成了一个测试模版的脚本在/usr/bin/bench_example,很简单的就知道怎么做了。
example如下:
```perl#!/usr/bin/perl -w 继续阅读……


java的中文支持

10 Jun 2011 Posted in  linux

往论坛上传图片,有的图片上有中文字,却显示成方框。求助了一下度娘,快速解决。记录一下:
* 第一步,在windows下找到simsun.ttc文件,嗯,ntfs系统下强力推荐everything小工具一个;
* 第二步,上传simsun.ttc到服务器的/usr/share/fonts/zh_CN/下,其他路径也行,不过这个路径比较通用;
* 第三步,在$JAVA_HOME/jrp/lib/下创建fontconfig.properties.zh文件,原型格式可见同目录下的fontconfig.properties.src。
fontconfig.properties.zh文件相关内容如下:
java allfonts.chinese-gbk=-misc-simsun-medium-r-normal--*-%d-*-*-p-*-gbk-0 allfonts.chinese-gb2312=-misc-simsun-medium-r-normal--*-%d-*-*-p-*-gb2312.1980-0 sequence.allfonts.GB18030=latin-1,chinese-gbk,chinese-cn-iso10646 sequence.allfonts.GBK=latin-1,chinese-gbk sequence.allfonts.GB2312=latin-1,chinese-gb2312 sequence.allfonts.UTF-8.ko.KR=latin-1,korean,japanese-x0208,japanese-x0201,chinese-gbk sequence.allfonts.UTF-8.ja.JP=latin-1,japanese-x0208,japanese-x0201,chinese-gbk,korean sequence.fallback=lucida,chinese-big5,chinese-gbk,japanese-x0208,korean filename.-misc-simsun-medium-r-normal--*-%d-*-*-p-*-gbk-0=/usr/share/fonts/zh_CN/simsun.ttc filename.-misc-simsun-medium-r-normal--*-%d-*-*-p-*-gb2312.1980-0=/usr/share/fonts/zh_CN/simsun.ttc awtfontpath.chinese-gb2312=/usr/share/fonts/zh_CN awtfontpath.chinese-gbk=/usr/share/fonts/zh_CN
很简单的一件小事儿,一来作个记录,二来测试微博同步——从百度统计看我可怜的一点点访问都来自微博…… 继续阅读……


perl模块Statistics::Descriptive

09 Jun 2011 Posted in  perl

今天写基调测试报告,需要从原始的ping延时和丢包率数据中自己计算标准方差以评估波动性(直接运行ping命令可见,不过基调报告里没有)。
方差是各个数据与其平均数的差的平方的平均数。标准差(均方差)则是方差的算术平方根。
这个时候可以打开excel……不过作为excel只会填文字的人,只好打开CPAN来解决问题了~
perl#!/usr/bin/perl -w use Statistics::Descriptive; use strict; open FH,'<','data'; my $data={}; while(<FH>){ my @F = split; push @{$data->{"快网延时"}}, $F[3]; push @{$data->{"快网丢包"}}, $F[4]; push @{$data->{"森华延时"}}, $F[6]; push @{$data->{"森华丢包"}}, $F[7]; push @{$data->{"帝联延时"}}, $F[9]; push @{$data->{"帝联丢包"}}, $F[10]; } close FH; my $stat = Statistics::Descriptive::Full->new(); foreach my $key (sort keys %{$data}) { $stat->add_data(@{$data->{"$key"}}); print $key."\t".$stat->standard_deviation(),"\n"; $stat->clear(); }
记住一定要clear,不然的话add_data会接着上一次的加,然后数据就错了。 继续阅读……


spread试验

09 Jun 2011 Posted in  perl

spread还是半年前的时候偶然看到的,一直没有试过。前段时间用gearman收集集群日志时,发现gearman的方式,worker不会知道client来自哪里,一条job只会一个worker来做,比较适合做分布式计算,但相比我最初设想的实时系统管理需求,还是有一定距离。于是重新翻出来spread,感觉可以根据应用系统设置不同的group,然后统一再由一个回收结果的group即可。于是有了如下试验: 继续阅读……


tmpfs的inode问题

09 Jun 2011 Posted in  linux

一些squid服务器为了强调加速效果,使用tmpfs来做cache_dir。刚开始运行的时候也嗖嗖的,不过没过一两天,mgr:info就看到缓存命中率急剧下降,字节命中率甚至只剩下10%左右!检查了多次配置,绝对没有问题,但同样的url,曾经一分钟几百次的HIT,现在一分钟几百次MISS……
df看,不管是tmpfs,还是logs所在的目录,都才用了不到30%。最后想起来df -i看了下,果然,tmpfs的inode使用率100%了!
赶紧remount了一次,解决了问题。但不是根本出路。还是得想办法搞定这个inode。
在linux代码说明里找到了关于tmpfs的文档(/usr/src/linux/Documentation/filesystems/tmpfs.txt):
tmpfs has three mount options for sizing:
……
nr_inodes: The maximum number of inodes for this instance. The default is half of the number of your physical RAM pages, or (on a
machine with highmem) the number of lowmem RAM pages,
whichever is the lower.
These parameters accept a suffix k, m or g for kilo, mega and giga and
can be changed on remount. The size parameter also accepts a suffix %
to limit this tmpfs instance to that percentage of your physical RAM:
the default, when neither size nor nr_blocks is specified, is size=50% 继续阅读……


用gearman汇总多台服务器的回滚日志

03 Jun 2011 Posted in  monitor

gearman其实不是重点,因为我就是抄了一遍perldoc的样例而已。关键在服务器上的log4j日志是回滚的,所以需要配合回滚(猜测log4j的DailyRollingFile回滚方式类似mv resin.log resin.log-ymd && reload,这样在回滚后,FH还在resin.log-ymd上,就读不到新日志了)重启FH。
另:tail命令有个参数-F/–follow=name,可以锁定文件名而不是文件描述符,不知道这个功能是怎么做到的?
一步一步来: 继续阅读……


HTML::Template试用

01 Jun 2011 Posted in  perl

给我自己的学习计划做个开头,从html::template开始试用。
首先利用上上篇的nmap.pl脚本,提取一些数据,然后展示在页面上。
cgi脚本如下:
perl#!/usr/bin/perl -w use HTML::Template; use XML::Simple; use Net::MySQL; #定期执行这个 #system("nmap -n -p 22,5666 10.168.168.0/23 10.168.170.0/24 -oX output.xml"); my $text = XMLin("output.xml"); #读取html模版 my $temp = HTML::Template->new(filename => '../template/html/server.tmpl'); my $localhost = '127.0.0.1'; my @array = (); my $i = 0; my $hash = {}; while ( $text->{host}->[$i] ) { #因为新增了ssh端口扫描,所以xml解析和前例稍有不同 my $ssh_state = $text->{host}->[$i]->{ports}->{port}->[0]->{state}->{state}; my $nrpe_state = $text->{host}->[$i]->{ports}->{port}->[1]->{state}->{state}; my $ip = ref($text->{host}->[$i]->{address}) eq 'ARRAY' ? $text->{host}->[$i]->{address}->[0]->{addr} : $text->{host}->[$i]->{address}->{addr}; my $mac = ref($text->{host}->[$i]->{address}) eq 'ARRAY' ? $text->{host}->[$i]->{address}->[1]->{addr} : '00:1E:C9:E6:E1:7C'; $i++; my $channel = &amp;mysql_query($mac); #将ip按照频道排成列表,每个ip存有ssh和nrpe状态 if ( exists $hash->{$channel} ) { push @{$hash->{$channel}}, { 'IP' => $ip, 'SSH' => $ssh_state, 'NRPE' => $nrpe_state, }; } else { $hash->{$channel}->[0] = { 'IP' => $ip, 'SSH' => $ssh_state, 'NRPE' => $nrpe_state, }; } } #将上面while生成的hash转成HTML::Template认可的array,不过array的单个元素可以是hash foreach my $key( keys %{$hash} ) { my $onechannel = {}; $onechannel->{"CHANNEL"} = $key; my $j = 0; foreach my $ip( @{$hash->{$key}} ) { $onechannel->{"IP_LOOP"}->[$j] = $ip; $j++; } push @array, $onechannel; } #将array传递给之前定义的html模版 #注意:不管是param还是@array里,所有的key必须都在tmpl里使用,冗余也会报错 $temp->param(CHANNEL_LOOP => \@array); #输出成html格式 print "Content-Type: text/html\n\n", $temp->output; #这段没什么说的,根据mac获取频道 sub mysql_query { my $mac = shift; my $mysql = Net::MySQL->new( hostname => $localhost, database => 'myops', user => 'myops', password => 'myops', ); $mysql->query("select channel from myhost where mac='$mac'"); &amp;alert("New server") unless $mysql->has_selected_record; my $a_record_iterator = $mysql->create_record_iterator(); while (my $record = $a_record_iterator->each) { return $record->[0]; }; } #留着后续继续处理 sub alert { print @_,"\n"; }
然后是template文件server.tmpl:
```html 继续阅读……