概述[作者] 网名: 猪头三 站点: http://www.x86asm.com Email: pliceman_110@163.com QQ: 643439947 编程生涯: 2001~至今[2014年] 职业生涯: 11年 开发语言: C/C++; x86asm; Object Pascal; Object-C; C#; 开发工具: VC++; Delphi; 研发领域: Windows应用软件安
[作者] 网名: 猪头三 站点: http://www.x86asm.com Email: pliceman_110@163.com QQ: 643439947 编程生涯: 2001~至今[2014年] 职业生涯: 11年 开发语言: C/C++; x86asm; Object Pascal; Object-C; C#; 开发工具: VC++; Delphi; 研发领域: windows应用软件安全; windows系统内核安全; windows系统磁盘数据安全; 技能种类: 逆向 驱动 磁盘 文件 [序言] 一直都不是linux服务器专业人员. 但恰恰自己又拥有2台国外服务器,上面有好多关于我国外软件的产品网站. 这2台服务器每天都遭受各种第3世界国家攻击以及主流国家恶意爬虫和wp_login.PHP攻击. 每次维护一次访问日记都需要1个多小时,很麻烦. 再一个linux命令苦涩难懂,勉强会用几个,但还是不顶用. 就在前几天心烦了,干脆自己写脚本解析日记算了. 就这个念头一闪,就诞生了这个perl脚本出来. [学习] perl语言认真看2个小时,然后再mac os x系统装上eclips+perl插件就开工了(备注: 不会用vi,因为人笨),断断续续用了2天时间终于完成了第一个版本,大约700多行. 在开发过程中,其实很简单: 就是把C语言的逻辑思维转换成perl代码. 为什么要这样做,因为脚本语言通病就是语法糖过多,会让你迷失在语法糖里面而无法写出正常的程序,不是每个开发人员有拥有那种开发语言的天赋(备注:我个人认为只有这样的天赋才能接受各种奇怪的语法糖). 也就是一直坚持这个原则才让这个perl脚本诞生. [差异] perl和python都很好上手,只要你有C语言基础,玩这个很简单. 比Js简单多了. 那我为什么用perl呢?其实是我的服务器默认没有安装python,倒反默认安装了ruby,比较神奇. 本来想用ruby的,因为我第一个脚本语言就是ruby,但是后来想想linux服务器一般大头都是perl语言,因此选择了perl而不是ruby. [源码] #!usr/bin/perl #作用: 监视服务器的网站目录下access-log文件夹里的日记记录 # 并分析日记里面的ip访问次数, 如果达到预警次数则自动发送email # 给管理员 #作者: 猪头三 http://www.x86asm.com #版本: v0.0.1 测试版 #时间: 2014-07-15 #留言: 本人不是linux系统专家, 因此写这个脚本是纯粹自己用用, # 如果你有更好的建议和方法请联系我. #使用方式: 按照提示修好源码之后, 就传到linux服务器并通过crontab -e加入计划任务定时执行即可 #解决其他路径下的模块包含问题 BEGIN { push @ INC , "/Users/PigheadThree/perl5/lib/perl5" ; } #use 5.010;
use strict ; use
autodIE ; use
Try :: Tiny ; use
TIE :: file ; use
Fcntl 'O_RDONLY' ; use
file :: Spec :: Functions qw ( rel2abs ) ; use
file :: Basename qw ( dirname basename ) ; use
file :: Spec ; use
file :: copy qw ( copy ); use
MIME :: lite ; use
MIME :: Base64 ; use
Authen :: SASL ; # 重要:如果服务器没有该模块将会导致email无法发送 #=================测试代码================== #=================全局变量================== #目录特征, 防止错误删除(表示你执行脚本要放在此目录下面)(可修改) my
$g_str_App_Flag = 'pht_monitor' ; #匹配access-logs的每条记录是否包含Google和bing机器人(可修改) #Google bing的ip都是合法ip my
$g_str_grep_Bot 'Googlebot|bingbot' ; #ip访问次数预警(可修改) my
$g_int_limit_VisitIp = 900 ; #服务器名称(可修改) my
$g_str_Servername "PHT Server" ; #自动发送email(可修改) my
$g_str_email_From 'xxxxxxx@163.com' ; my
$g_str_email_Pass 'xxxxxxx' ; my
$g_str_eamil_Smtp 'smtp.163.com' ; my
$g_str_eamil_To 'xxxxxxx@qq.com' ; #=================函数入口点================== try { & fun_RunningLog ( "main() start..." ) ; &
main () ; "main() end."
) ; catch "===========main() running error==========="
) ; }; sub
main () #比如你的服务器存存在一个站点 www.x86asm.com #那么该服务器内部会有一个专门的文件夹存放该站点的所有文件 #假设为: x86asm #那么该目录下会存放一个名为x86asm.com的日记文件,一般路径如下 #/home/x86asm/access-logs/x86asm.com
#我们可以通过分析这个日记文件来得到ip的访问次数 my $str_Site_URL "www.x86asm.com" ; my
$str_Site_name "x86asm_" ; my
$str_Site_LogfilePath "/home/x86asm/access-logs/x86asm.com" ; fun_CountTargetSite ( $str_Site_URL $str_Site_name $str_Site_LogfilePath ) ; } #End main() #=================函数====================== #统计目标网站的ip访问次数 #param_1 : 目标网站域名 #param_2 : 目标网站简称 #param_3 : 目标网站access_log文件路径 sub
fun_CountTargetSite () #本函数不支持0参数传递 if
(@ _ != 3 ) { return 0 ; } ( my $str_param_Site_URL my $str_param_Site_name my $str_param_Site_LogfilePath ) = @ _ ; my % hash_VisitIp_Count ; "[$str_param_Site_URL] : start..."
); &
fun_GetVisitIp ( $str_param_Site_LogfilePath $g_int_limit_VisitIp & fun_GetLocaltime ( "/" ) \% hash_VisitIp_Count ) ; if ( & fun_IsNeedUpdate ( $str_param_Site_name .& fun_GetLocaltime ( "_" ) . ".txt" \% hash_VisitIp_Count ) eq 1 ) #保存最新统计 & fun_VisitIpSavetoCurrentPathfile ( $str_param_Site_name \% hash_VisitIp_Count ); #发送EMAIL my $str_SendEmail_Data = & fun_GetSendEmailToData ( $str_param_Site_name ".txt" ) ; if ( $str_SendEmail_Data ne 0 ) { & fun_autoSendEmailToAlarm ( $g_str_Servername "[$str_param_Site_URL]" "Alarm Ip Visit" $str_SendEmail_Data ) ; } else } "[$str_param_Site_URL] : end." ); # End fun_CountTargetSite() #获取本地时间 #param_1 : 时间分隔符 sub
fun_GetLocaltime () #月份对照表 %
hash_montoname = ( "01" => "Jan" "02" "Feb" "03" "Mar" "04" "Apr" "05" "May" "06" "Jun" "07" "Jul" "08" "Aug" "09" "Sep" "10" "Oct" "11" "Nov" "12" "Dec" ) ; my
( $sec $min $hour $mday $mon $year_off $wday $yday $isdat ) = localtime ; ( $mday $mon $year_off ) sprintf ( "%02d" $mday ) $mon +1 ) $year_off +1900 ); #月份转换为英文描述 $mon = $hash_montoname { $mon } ; return $mday . $_ [ 0 ] . $mon . $year_off ; # End fun_GetLocaltime()
#用于日记记录的时间格式 sub
fun_GetLocaltimetoLog () #本函数不支持参数传递 if
(@ _ ) my
@ array_montoname = qw ( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ) ; ( $sec $min $hour $mday $sec ) $min ) $hour ) = $array_montoname [ $mon ] ; '/'
. $year_off ' ' . $hour ':' . $min . $sec ; # End fun_GetLocaltimetoLog()
#日记记录 #param_1 : 日记内容 sub
fun_RunningLog () #本函数不支持0个参数传递 my
$str_param_Print ) #获取时间 my
$str_LogTime '[' .& fun_GetLocaltimetoLog () ']' ; #打开日记文件, 如果没有则创建 my
$str_Log_filename 'run_' '_' ) '.txt' ; $str_Log_filename = file :: Spec -> join ( & fun_GetCurrentAppPath () $str_Log_filename ) ; unless ( - e $str_Log_filename ) unless
( open ( HANDLE_OPEN ">$str_Log_filename" )) ">>$str_Log_filename" )) #开始写入 print
HANDLE_OPEN $str_LogTime ' : ' . $str_param_Print "\n" ; close
( HANDLE_OPEN ) ; 1
; #End fun_RunningLog()
#获取当前执行目录 sub
fun_GetCurrentAppPath () return
dirname ( rel2abs ( __file__ )) ; # End fun_GetCurrentAppPath()
#复制目标文件到当前目录 #param_1 : 需要复制到目标文件全路径 sub
fun_copyfileToCurrentAppPath () my
$str_copyfiletopath "" ; my
$str_copyfilename my $str_CurrentAppPath my $str_param_copyfilePath = $_ [ 0 ] ; #判断文件是否存在 -e 表示 文件 -d 表示目录 -
e $str_param_copyfilePath ) #开始复制(先执行旧文件删除) $str_CurrentAppPath & fun_GetCurrentAppPath () ; $str_copyfilename = basename ( $str_param_copyfilePath ) ; $str_copyfiletopath join ( $str_CurrentAppPath $str_copyfilename ) ; - e $str_copyfiletopath ) { #删除旧文件 if ( $str_copyfiletopath =~ /$g_str_App_Flag/i ) { "fun_copyfileToCurrentAppPath() deleteing $str_copyfiletopath..."
) ; unlink ( $str_copyfiletopath ); "fun_copyfileToCurrentAppPath() deleted $str_copyfiletopath."
) ; } } copy ( $str_param_copyfilePath $str_copyfiletopath ) ; return
$str_copyfiletopath ; # End fun_copyfileToCurrentAppPath()
#正则表达式提取ip地址 sub
fun_GetIpByStr () my
$str_param_Target ) if ( $str_param_Target /(\d+\.\d+\.\d+\.\d+)/ ) return
"" ; #IP地址 # End fun_GetIpBystr()
#统计目标ip访问次数 #param_1 : 目标访问日记文件路径 #param_2 : IP访问次数报警 #param_3 : 目标时间时间到访问记录 (02/jul/2014) #param_4 : 哈希表 (地址传递) sub
fun_GetVisitIp () 4
) #获取参数 my
$str_param_VisitIp_LogfilePath my $int_param_VisitIp_Count my $time_param_Get my $hash_param_VisitIp ) if ( $time_param_Get eq "NO" ) $time_param_Get "/" ) ; #开始统计 -
e $str_param_VisitIp_LogfilePath ) my
$str_VisitIp_copytopath & fun_copyfileToCurrentAppPath ( $str_param_VisitIp_LogfilePath ) ; if
( $str_VisitIp_copytopath eq #获取日记文件失败 #打开日记文件 my
@ array_VisitIp_Load ; my
$int_VisitIp_filelineNums ; -
e $str_VisitIp_copytopath ) tIE
@ array_VisitIp_Load 'TIE::file' $str_VisitIp_copytopath mode => O_RDONLY ; #获取行数 $int_VisitIp_filelineNums = @ array_VisitIp_Load - #逆向循环匹配 my $str_Temp_line my $str_Temp_VisitIp my $str_Temp_VisitIp_Count 0 ; % hash_Temp_VisitIp = () ; while
( $int_VisitIp_filelineNums >= $str_Temp_line = $array_VisitIp_Load [ $int_VisitIp_filelineNums ] ; if ( $str_Temp_line /$time_param_Get/i ) /$g_str_grep_Bot/i ) { } @H_607_4035@
#捕获ip地址 $str_Temp_VisitIp & fun_GetIpByStr ( $str_Temp_line ) ; if ( $str_Temp_VisitIp eq { } #保存ip地址以及访问次数(临时) if ( exists $hash_Temp_VisitIp { $str_Temp_VisitIp }) { $hash_Temp_VisitIp { $str_Temp_VisitIp } += #判断是否大于报警次数,如果大于则保存 if ( $hash_Temp_VisitIp { $str_Temp_VisitIp } >= $int_param_VisitIp_Count ) { exists $$hash_param_VisitIp { $str_Temp_VisitIp }) { $$hash_param_VisitIp { $str_Temp_VisitIp } 1 ; } = $int_param_VisitIp_Count ; } } last ; $int_VisitIp_filelineNums -= 1 ; #关闭文件 untIE
@ array_VisitIp_Load ; 1
; "fun_GetVisitIp() $str_param_VisitIp_LogfilePath no found." ) ; # End fun_GetVisitIp()
#把哈希表到内容保存到当前执行目录下 #param_1 : 文件名称 #param_2 : 哈希内容 sub
fun_VisitIpSavetoCurrentPathfile () 2
) my
$str_param_Savetofilename my $hash_param_Conent ) #校验参数 if
(( length ( $str_param_Savetofilename ) == 0 ) or (( keys % $hash_param_Conent ) 0 )) #开始保存 my
$str_SavetofilePath $str_param_Savetofilename ) ; - e $str_SavetofilePath ) if
( $str_SavetofilePath "fun_VisitIpSavetoCurrentPathfile() deleteing $str_SavetofilePath..." ) ; unlink ( $str_SavetofilePath ); "fun_VisitIpSavetoCurrentPathfile() deleted $str_SavetofilePath."
) ; open
( HANDLE_file ">$str_SavetofilePath" )) my
$hash_Keys ; my
$hash_Values ; foreach
$hash_Keys ( sort % $hash_param_Conent ) $hash_Values = $$hash_param_Conent { $hash_Keys } ; print
HANDLE_file "$hash_Keys => $hash_Values \n" ; close
( HANDLE_file ) ; # End fun_VisitIpSavetoCurrentPathfile()
#判断是否需要更新日记文件(.txt) sub
fun_IsNeedUpdate () my
$str_param_filename length ( $str_param_filename ) ( % $hash_param_Conent my $bool_IsNeedUpdate 0 ; #更新标志位 my $str_Ip % hash_Load_Ip ; my
$str_OpenfilePath $str_param_filename ) ; #打开文件并匹配ip是否有更新 -
e $str_OpenfilePath ) open
( HANDLE_OPEN $str_OpenfilePath )) while
( my $str_Temp_line < HANDLE_OPEN > ) $str_Ip if ( $str_Ip eq { } @H_607_4035@ # 保存之前统计过的ip $hash_Load_Ip { $str_Ip } 1 ; close ( HANDLE_OPEN ); #开始循环匹配 my
$str_Temp_Value ; while
(( $str_Ip $str_Temp_Value ) each #判断ip是否是存在, 如果不存在则表示需要更新, 返回1 exists $hash_Load_Ip { $str_Ip }) { } $bool_IsNeedUpdate @H_607_4035@ } } #没有日记记录文件也表示需要更新 $bool_IsNeedUpdate return $bool_IsNeedUpdate ; # End fun_IsNeedUpdate()
#自动发送email进行报警 #param_1 : 标题 #param_2 : 内容 sub
fun_autoSendEmailToAlarm () my
$str_param_Subject my $str_param_Data ) length ( $str_param_Subject ) ( length ( $str_param_Data ) == 0 )) { 0 } my $msg_Send = MIME :: lite -> new ( From => $g_str_email_From To => $g_str_eamil_To Subject => $str_param_Subject Data => $str_param_Data ) ; #$msg_Send->attr("content-type" => "text/HTML") ; $msg_Send send ( "smtp" $g_str_eamil_Smtp AuthUser => $g_str_email_From AuthPass => $g_str_email_Pass Timeout => 30 ) ; # DeBUG => 1 表示打印发送时的各种状态记录 # End fun_autoSendEmailToAlarm() #从指定文件获取内容当作email内容进行发送 #param_1 : 目标文件名 (默认只在当前目录下获取) sub fun_GetSendEmailToData () my $str_param_filename ) #开始打开文件 my $str_Content chomp ( $str_Temp_line ) ; $str_Content .= $str_Temp_line .= "\n" ; length ( $str_Content ) return $str_Content ; # End fun_GetSendEmailToData() 总结
以上是内存溢出为你收集整理的2个小时拿下Perl语言:自动监控服务器内网站访问ip次数并预警(附源码)全部内容,希望文章能够帮你解决2个小时拿下Perl语言:自动监控服务器内网站访问ip次数并预警(附源码)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
评论列表(0条)