<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>smallfish logs &#187; Perl</title>
	<atom:link href="http://chenxiaoyu.org/blog/archives/category/perl/feed" rel="self" type="application/rss+xml" />
	<link>http://chenxiaoyu.org</link>
	<description>关注 Python &#38; Go &#38; PostgreSQL</description>
	<lastBuildDate>Sat, 07 Aug 2010 10:31:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Apache Mod_Perl实现 URL Rewrite</title>
		<link>http://chenxiaoyu.org/blog/archives/123</link>
		<comments>http://chenxiaoyu.org/blog/archives/123#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:33:07 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=123</guid>
		<description><![CDATA[相信apache的mod_rewrite模块都很熟悉了，今天这儿换个思路，利用mod_perl来实现下，发现竟然是如此的简单！
首先得保证apache已经安装了mod_perl模块，具体安装配置可以看上一篇文章哦。
修改下http.conf配置，添加一下内容：

PerlTransHandler MyTrans # MyTrans 这个是自己添加的处理模块名

具体MyTrans.pm脚本如下：

package MyTrans;

use strict;
use Apache2::Const qw(DECLINED);

sub handler {
    my $r = shift;
    my $uri = $r-&#62;uri;
    my ($id) = ($url =~ m&#124;^/news/(.*)\.html&#124;);
    $r-&#62;uri("/news.php");
    $r-&#62;args("id=$id");
    return Apache2::Const::DECLINED;
}
1;

实现就是：/news/12345.html  =&#62; /news.php?id=12345

© smallfish for smallfish logs, 2009. &#124;
Permalink [...]]]></description>
			<content:encoded><![CDATA[<p>相信apache的mod_rewrite模块都很熟悉了，今天这儿换个思路，利用mod_perl来实现下，发现竟然是如此的简单！</p>
<p>首先得保证apache已经安装了mod_perl模块，具体安装配置可以看上一篇文章哦。</p>
<p>修改下http.conf配置，添加一下内容：</p>
<pre>
PerlTransHandler MyTrans # MyTrans 这个是自己添加的处理模块名
</pre>
<p>具体MyTrans.pm脚本如下：</p>
<pre>
package MyTrans;

use strict;
use Apache2::Const qw(DECLINED);

sub handler {
    my $r = shift;
    my $uri = $r-&gt;uri;
    my ($id) = ($url =~ m|^/news/(.*)\.html|);
    $r-&gt;uri("/news.php");
    $r-&gt;args("id=$id");
    return Apache2::Const::DECLINED;
}
1;
</pre>
<p>实现就是：/news/12345.html  =&gt; /news.php?id=12345</p>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/123">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/123#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/123&title=Apache Mod_Perl实现 URL Rewrite">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/perl" rel="tag">Perl</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/123/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache Mod_Perl 防盗链</title>
		<link>http://chenxiaoyu.org/blog/archives/120</link>
		<comments>http://chenxiaoyu.org/blog/archives/120#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:31:15 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=120</guid>
		<description><![CDATA[大体思路是这样的，比如有 一个地址：http://www.aa.com/down/1.mp3，不幸搜索引擎或者迅雷扒到了，就无偿为他们奉献流量了。 但是假如在http://www.aa.com/down/1.mp3?key=123，key参数每天变化或者几分钟变化一次，在apache服务端校 验下这个参数，不正确则显示拒绝访问或者找不到的话，那样防盗链的效果就算达到了把。
modperl强大到可以任意应用apache内部API，官方地址是：http://perl.apache.org 。根据apache版本选择相应的modperl版本，现在大部分都apache2了，就选择modperl2把。具体安装配置可以看官方文档。
先建立/home/httpd/modperl/startup.pl(目录请自行修改)，内容如下：
use strict;

use lib qw(/home/httpd/modperl); # 把这个路径加入到perl lib路径

use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Connection ();
use Apache2::RequestUtil ();
use Apache2::ServerUtil ();
use Apache2::Log ();
use Apache2::Request ();

1;
部分本机httpd.conf配置：

LoadModule perl_module                modules/mod_perl.so
LoadModule apreq_module             modules/mod_apreq2.so
PerlPostConfigRequire /home/httpd/modperl/startup.pl
&#60;Location /down &#62;
    SetHandler modperl # 设置该目录交给modper处理
    PerlAccessHandler Down # Down是模块名称
    [...]]]></description>
			<content:encoded><![CDATA[<p>大体思路是这样的，比如有 一个地址：http://www.aa.com/down/1.mp3，不幸搜索引擎或者迅雷扒到了，就无偿为他们奉献流量了。 但是假如在http://www.aa.com/down/1.mp3?key=123，key参数每天变化或者几分钟变化一次，在apache服务端校 验下这个参数，不正确则显示拒绝访问或者找不到的话，那样防盗链的效果就算达到了把。</p>
<p>modperl强大到可以任意应用apache内部API，官方地址是：<a href="http://perl.apache.org/" target="_blank">http://perl.apache.org</a> 。根据apache版本选择相应的modperl版本，现在大部分都apache2了，就选择modperl2把。具体安装配置可以看官方文档。</p>
<p>先建立/home/httpd/modperl/startup.pl(目录请自行修改)，内容如下：</p>
<pre>use strict;

use lib qw(/home/httpd/modperl); # 把这个路径加入到perl lib路径

use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Connection ();
use Apache2::RequestUtil ();
use Apache2::ServerUtil ();
use Apache2::Log ();
use Apache2::Request ();

1;</pre>
<p>部分本机httpd.conf配置：</p>
<pre>
LoadModule perl_module                modules/mod_perl.so
LoadModule apreq_module             modules/mod_apreq2.so
PerlPostConfigRequire /home/httpd/modperl/startup.pl
&lt;Location /down &gt;
    SetHandler modperl # 设置该目录交给modper处理
    PerlAccessHandler Down # Down是模块名称
    PerlSetVar key 123 # 设置校验参数值
&lt;/Location&gt;
</pre>
<p>mod_apreq2.so这个模块需要安装Apache2::Request，具体安装：<a href="http://pyh7.spaces.live.com/blog/cns%2147D8D44208AC51E5%21128.entry" target="_blank">http://pyh7.spaces.live.com/blog/cns!47D8D44208AC51E5!128.entry</a></p>
<p>startup.pl文件一般modperl应用都有，加载一些常用库，可以在apache启动时预先载入，避免重复加载。</p>
<p>修改这些后可以重启下apache，看下logs/error_log里最后是否有mod_apreq和mod_perl字样，如果有就说明成功了。剩下都就是写校验的perl脚本了，/home/httpd/modperl/Down.pm，内容如下：</p>
<pre>
package Down;
use strict;
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Connection ();
use Apache2::RequestUtil ();
use Apache2::ServerUtil ();
use Apache2::Log ();
use Apache2::Const -compile =&gt; qw(OK FORBIDDEN);
use Apache2::Request ();

sub handler {
    my $r = shift;
    my $req = Apache2::Request-&gt;new($r);
    my $ip = $r-&gt;connection-&gt;remote_ip;
    my $k = $req-&gt;param('key') || ''; # 判断访问时是否带key参数
    my $key = $r-&gt;dir_config('key') || '123'; # 加载httpd.conf配置中的key值
    if ($key eq $k) { # 相等可以正常访问
        return Apache2::Const::OK;
    } else { # 否则显示拒绝访问
        my $s = Apache2::ServerUtil-&gt;server;
        $s-&gt;log_error("[$ip--------forbidden.]");
        return Apache2::Const::FORBIDDEN;
    }
}

1;
</pre>
<p>提示一下，以上两个perl脚本文件末尾记得加上1;</p>
<p>重启下apache。现在可以通过http://www.aa.com/down/1.mp3和http://www.aa.com/down /1.mp3?key=123测试下。可以看见不加参数拒绝访问了把。这里只是简单的判断，实际上可以根据日期或者IP加密生成一个字符串来判断。</p>
<p>写这个帖子完全是无意中搜索modperl应用时候发现了，具体可以参见：<br />
<a href="http://pyh7.spaces.live.com/blog/cns%2147D8D44208AC51E5%21140.entry" target="_blank">http://pyh7.spaces.live.com/blog/cns!47D8D44208AC51E5!140.entry</a></p>
<p>上面的文档已经写都很详细了，包括怎么安装modperl、Apache2::Request等模块以及配置apache的http.conf就不在累赘都重复了。</p>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/120">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/120#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/120&title=Apache Mod_Perl 防盗链">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/perl" rel="tag">Perl</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/120/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Perl 批量跳过 MySQL Slave 复制错误</title>
		<link>http://chenxiaoyu.org/blog/archives/107</link>
		<comments>http://chenxiaoyu.org/blog/archives/107#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:19:12 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=107</guid>
		<description><![CDATA[发现mysql slave服务器经常因为一些特殊字符或者符号产生的更新语句报错，整个同步也会因此而卡在那，最初的办法只是手动去出错的机器，执行下面三条sql语句，跳过错误即可。

slave stop;
set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
slave start;

一台slave机器用这样方法还行，多台就麻烦了，就顺手写了个简单的perl脚本，方便统一跳过错误，代码如下：

#!/usr/bin/env perl
use strict;
use warnings;

# get slave status
sub get_status {
    my ($ip, $usr, $pass) = @_;
    my $info = `mysql -u$usr -p$pass -h$ip -e 'show slave status\\G;'`;
    if (($info =~ /Slave_IO_Running: Yes/) &#38;&#38; ($info =~ /Slave_SQL_Running: No/)) {
     [...]]]></description>
			<content:encoded><![CDATA[<p>发现mysql slave服务器经常因为一些特殊字符或者符号产生的更新语句报错，整个同步也会因此而卡在那，最初的办法只是手动去出错的机器，执行下面三条sql语句，跳过错误即可。</p>
<pre>
slave stop;
set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
slave start;
</pre>
<p>一台slave机器用这样方法还行，多台就麻烦了，就顺手写了个简单的perl脚本，方便统一跳过错误，代码如下：</p>
<pre>
#!/usr/bin/env perl
use strict;
use warnings;

# get slave status
sub get_status {
    my ($ip, $usr, $pass) = @_;
    my $info = `mysql -u$usr -p$pass -h$ip -e 'show slave status\\G;'`;
    if (($info =~ /Slave_IO_Running: Yes/) &amp;&amp; ($info =~ /Slave_SQL_Running: No/)) {
        return 1;
    }
    return 0;
}
# mysql slave skip
sub slaveskip {
    my ($ip, $usr, $pass) = @_;
    print "slave error **\n";
    system("mysql -u$usr -p$pass -h$ip -e 'slave stop;'");
    system("mysql -u$usr -p$pass -h$ip -e 'set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;'");
    system("mysql -u$usr -p$pass -h$ip -e 'slave start;'");
}

my @hosts = qw/
192.168.0.101:root:tt1234
192.168.0.102:root: tt1234
192.168.0.103:root: tt1234
/;
foreach (@hosts) {
    my ($ip, $usr, $pass) = split ':';
    print "// ----- $ip\n";
    my $count = 1;
    while ($count &lt; 100000) {
        my $status = get_status($ip, $usr, $pass);
        print "i: $count status: $status\n";
        last if $status == 0;
        slaveskip($ip, $usr, $pass);
        select(undef, undef, undef, 0.1);
        $count++;
    }
    print "\n";
}

exit;
</pre>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/107">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/107#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/107&title=Perl 批量跳过 MySQL Slave 复制错误">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/mysql" rel="tag">MySQL</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/perl" rel="tag">Perl</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/107/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用 Perl 快速解析 Apache Log</title>
		<link>http://chenxiaoyu.org/blog/archives/100</link>
		<comments>http://chenxiaoyu.org/blog/archives/100#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:11:24 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=100</guid>
		<description><![CDATA[功能简述
统计出日志里一个或多个页面总共访问的次数，比如aa.jsp, bb.jsp这样页面分别多少次。
实现简述
Apache单个日志文件800M。
最初程序使用Python编写，按行来统计，分别使用in(最慢)和index方法去查找，然后使用了正则匹配，程序运行时间从最初的1分50多秒优化到1分10秒左右，参考了qyb博客中提到的gc.disable()，有了一定的提升，最终还是需要1分左右。
然后随意用了Perl写了一个，用了最土鳖的&#60;LOG&#62;这样的按行分析，最后正则匹配，然后++，速度竟然在40-50秒之间，惊叹！后来经过shucho指点，在正则部分采用了预编译，效果那是相当惊人！800M文件只用了7秒左右。卧槽！
程序片段
# --------------------------------------------------------------------
use strict;
use Benchmark;

my $LOG_FILE = '/usr/local/apache/logs/access.log';
# 下面qr部分起了关键作用，预编译了表达式
my @EXT_LIST = map {qr/$_/} qw{
aaServlet
bbServlet
};

my $startime = new Benchmark;
my %result;
map {$result{$_} = 0} @EXT_LIST;
open LOG_FILE, $LOG_FILE;
while (&#60;LOG_FILE&#62;){
    foreach my $ext (@EXT_LIST){
        $result{$ext}++ if $_ =~ /$ext/;
    }
}
close LOG_FILE;

while (my ($key, $value) = each(%result)){
 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>功能简述</strong></p>
<p>统计出日志里一个或多个页面总共访问的次数，比如aa.jsp, bb.jsp这样页面分别多少次。</p>
<p><strong>实现简述</strong></p>
<p>Apache单个日志文件800M。</p>
<p>最初程序使用Python编写，按行来统计，分别使用in(最慢)和index方法去查找，然后使用了正则匹配，程序运行时间从最初的1分50多秒优化到1分10秒左右，参考了<a href="http://www.dup2.org/node/1006" target="_blank">qyb</a>博客中提到的gc.disable()，有了一定的提升，最终还是需要1分左右。</p>
<p>然后随意用了Perl写了一个，用了最土鳖的&lt;LOG&gt;这样的按行分析，最后正则匹配，然后++，速度竟然在40-50秒之间，惊叹！后来经过<a href="http://shucho.org/blog/" target="_blank">shucho</a>指点，在正则部分采用了预编译，效果那是相当惊人！800M文件只用了7秒左右。卧槽！</p>
<p><strong>程序片段</strong></p>
<pre># --------------------------------------------------------------------
use strict;
use Benchmark;

my $LOG_FILE = '/usr/local/apache/logs/access.log';
# 下面qr部分起了关键作用，预编译了表达式
my @EXT_LIST = map {qr/$_/} qw{
aaServlet
bbServlet
};

my $startime = new Benchmark;
my %result;
map {$result{$_} = 0} @EXT_LIST;
open LOG_FILE, $LOG_FILE;
while (&lt;LOG_FILE&gt;){
    foreach my $ext (@EXT_LIST){
        $result{$ext}++ if $_ =~ /$ext/;
    }
}
close LOG_FILE;

while (my ($key, $value) = each(%result)){
    $key =~ s/\(\?-xism:(.*?)\)/$1/g;
    print "$key:\t$value\n";
}

printf "** %s\n\n", timestr(timediff(new Benchmark, $startime));</pre>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/100">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/100#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/100&title=使用 Perl 快速解析 Apache Log">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/perl" rel="tag">Perl</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/100/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
