Perl提取wtmpx日志最近用户登录信息写到系统日志Syslog里

背景知识:

  1. Perl读取wtmpx日志文件》;
  2. logger命令;
  3. Syslog日志;
  4. crontab命令;

参考书籍:

  • Perl网络编程

求助:

  • Sys::Syslog模块处理系统日志编译警告:your vendor has not defined the Sys::Syslog macro _PATH_LOG...
    求各位大大解惑,不胜感激。

源码如下:

#!/usr/bin/perl -w
########################################################################################
# 文件:wtmpx2.pl
# 功能:从wtmpx日志里找出最近登录信息写到系统日志里;
# 作者:半点闲
# 时间:2012-11-11 11:55 光棍节快乐
# 系统:SCO_SV scosysv 3.2 5.0.6 i386 Perl5.6.0 built for i486-pc-sco3.2v5.0
# 说明:所使用的系统日志功能很弱无法提供登录到系统用户的信息,结合cron定时执行本程序,将提取到
# 的登录信息写到系统日志里.同时,机房采用"集中日志服务器"统一接收系统发送到远端日志进行集中分
# 析处理.
#
# 进一步说明:
# 系统比较陈旧,因是生产用机即不能升级现在又无法更换在,使用Sys::Syslog模块处理系统日志时,
# 在Ubuntu+Perl5.14正常的代码,在本机上无法编辑通过提示:
# your vendor has not defined the Sys::Syslog macro _PATH_LOG...
# <>书中找到一段话:在Perl5.6之前,为了运行这个模块需要syslog.ph头文件,
# 但这个文件不和Perl发布版一起提供,需要使用h2ph工具手工产生.在使用Sys::Syslog之前应当
# 升级5.6或更高版本。
# 我的Perl版本按书上所说是满足要求的,难道好事都让我遇到了,不解!想起Perl名言"TMOTWTDI"
# 日志部分暂时交给shell的logger命令处理.
# --------------------------------------------------------------------------------------
# 修改:2012-11-12
# BUG1:时间精度缺失造成重复记录的问题;
# BUG语句:
# my ($sec,$min,$hour,$mday,$mon,$year_off) =  (localtime)[0..5];
# ($sec,$min,$hour,$mday,$mon,$year_off) =  (localtime $tv_sec)[0..5];
# 影响语句:next if($first_time >= $tv_time);
# 描述:如当前时间为11:00:00用做数字写入文件时为1100,此时,wtmpx文件中若有登录时间为10:01:01
# 将造成(1100>=100101)返回假值.
# 更正:全部以字符方式运算
# $sec = sprintf "%02d",$sec;	#不足2位补0
# $min = sprintf "%02d",$min;
# $hour = sprintf "%02d",$hour;
# 同时修改下述语句:
# next if($current_date ne $tv_date);
# next if($first_time ge $tv_time);
########################################################################################
use strict;

$SIG {__WARN__} = \&log_warn;

sub log_warn(){
	#warn信息也写到日志里;
	system "echo '@_' | logger -it wtmpx -p auth.info";
}

my $wtmpx_file = '/var/adm/wtmpx';
my $first_file = "/var/adm/first";						#记录前一次查询的时间
my $template = 'A32 A4 A32 s s s s l l l x20 s Z257 x';#ScoUnix5模版
my $recordsize = length( pack( $template, () ) );
my ($sec,$min,$hour,$mday,$mon,$year_off) =  (localtime)[0..5];
my $current_date = $year_off + 1900 . $mon + 1 . $mday;
$sec = sprintf "%02d",$sec;								#不足2位补0
$min = sprintf "%02d",$min;
$hour = sprintf "%02d",$hour;

my $session = open FIRST_FILE, '+<', $first_file or warn "Unable to open $first_file:$!\n";
my $first_time;												#前次查询的时间
if ($session){
	$first_time = ;							#获取先前的时间
	seek FIRST_FILE, 0, 0;									#移到文件头
	print FIRST_FILE "$hour$min$sec";								
	close FIRST_FILE or warn "Unable to close $first_file:$!\n";
} else {
	$first_time = "$hour$min$sec";							#使用当前时间
	$session = open FIRST_FILE, '>', $first_file or warn "err2:Unable to open $first_file:$!\n";
	if ($session){
		print FIRST_FILE $first_time;
		close FIRST_FILE or warn "err2:Unable to close $first_file:$!\n";
	}
}
	
open WTMP, '<', $wtmpx_file or die "Unable to open wtmpx:$!\n";

my ($ut_user, $ut_id,
	$ut_line, $ut_pid,
	$ut_type, $ut_e_termination,
	$ut_e_exit, $tv_sec,
	$tv_usec, $ut_session, 
	$ut_syslen, $ut_host) = ();

my $record;
while( read( WTMP, $record, $recordsize ) ) {
	($ut_user, $ut_id,
	$ut_line, $ut_pid,
	$ut_type, $ut_e_termination,
	$ut_e_exit, $tv_sec,
	$tv_usec, $ut_session,
	$ut_syslen, $ut_host) = unpack( $template, $record );
	
	next if $ut_type == 8;							#忽略退出的用户
	
	($sec,$min,$hour,$mday,$mon,$year_off) =  (localtime $tv_sec)[0..5];
	my $tv_date = $year_off + 1900 . $mon + 1 . $mday;
	$sec = sprintf "%02d",$sec;
	$min = sprintf "%02d",$min;
	$hour = sprintf "%02d",$hour;
	my $tv_time = "$hour$min$sec";
	
	next if($current_date ne $tv_date);			#跳过非当前系统日期的记录(当字符串进行比较)
	next if($first_time ge $tv_time);			#跳过前次查询过的记录(此句只能放在日期比较后面)
	
	if ($ut_id eq 'ftp'){
		$ut_user = "FTP LOGIN $ut_user";
	} else { 
		$ut_user = "LOGIN $ut_user"; 
	}
	
	my $format_record = "$ut_user:$ut_id:$ut_line:PID:$ut_pid:TYPE:$ut_type:HOST:$ut_host:$tv_date $hour:$min:$sec";
	system "echo '$format_record' | logger -it wtmpx -p auth.info";
}
close WTMP; 


写入Syslog日志效果图:

日志服务器接收效果图:

你可能感兴趣的:(OS/Network,crontab,logger,perl,Sco,Unix,syslog)