=============savePostfixLog.sh脚本代码===============
#!/bin/bash
# added to the rsyslog configuration files, let sh save error log to different letters in different files
# ------------install sh------------------
#
# a) cd this_sh_dir_path
# b) chmod 705 ./savePostfixLog.sh
# c) use ftp user to mkdir ./log
# b) ./savePostfixLog.sh -install
getShPath () {
if [ "`expr \"$0\" : '\(.\)'`" == "/" ];then #like /var/www/sh.sh
echo "$0"
return 0;
fi
if [ "`expr \"$0\" : '\(.\)'`" == "." ];then #like ./sh.sh or ./../../sh.sh
local newDir=${0#'./'}
echo "`pwd`/$newDir"
return 0;
fi
echo "$0" #unkown type
return 0
}
# get args[1]
logStr=$1
shDir=`getShPath`
echo "sh path : $shDir"
shDir=`dirname $shDir`
logPath="$shDir/log"
if [ "$logStr" = "-install" ];then # install this sh
if [ "$UID" -ne 0 ];then
echo 'install mode must run on root'
exit 0
fi
echo "chmod $shDir to 701"
`chmod 701 $shDir`
if [ ! -e "$logPath" ];then
echo "please use ftp user to mkdir $logPath"
exit 0
fi
if [ ! -d "$logPath" ];then
`rm $logPath`
echo "exsit a file and deleted:$logPath,please use ftp user to mkdir $logPath"
exit 0
fi
echo "chmod $logPath to 707"
`chmod -R 707 $logPath`
echo '
run under line command test,if no error is succse
-----------test command-----------
sudo -u change_this_to_rsyslog_user_name ./savePostfixLog.sh "from=<a_0@a.com> status=bounced "
-----------command end------------
if it is ok,add unline config in /etc/rsyslog.d/50-default.conf for send mail log to this sh
---------rsyslog config--------
$template mailFormat,"%msg%"
'
echo "mail.* ^$shDir/savePostfixLog.sh;mailFormat"
echo '
-------------config end--------
restart rsyslog use command : /etc/init.d/rsyslog restart
test send a letter you can see ./sh/log/ have same new file,it is log,the log name is letter DB_ID
and you can use rsyslog debug to see what is send to sh:where you send email,the run rsyslogd shell will show some thing
a) stop rsyslog use :/etc/init.d/rsyslog stop
b) start debug use :rsyslogd -n
c) exit debug on another shell input : kill -9 rsyslogd_PID
'
exit 0
fi
if [ -z "$logStr" ] ;then # empty
echo "empty logstr and exit"
exit 0
elif [ -n "`expr "$logStr" : '.*\( status=sent \)'`" ];then # is sent ok log
echo "sent log exit"
exit 0
elif [ -n "`expr "$logStr" : '.*\( status\=bounced \)'`" ] && [ -z "`expr "$logStr" : '.*\(loops back to myself\)'`" ]
then # is bounced log, send back mail, but no include local bounced
echo "bounced log"
elif [ -n "`expr "$logStr" : '.*\( status\=deferred \)'`" ] && [ -z "`expr "$logStr" : '.*\(\from=<>\)'`" ]
then # is deferred log, send back mail, but no include local deferred
echo "deferred log"
elif [ -n "`expr "$logStr" : '.*\(Recipient address rejected\: Domain not found;\)'`" ];then # is no exist domain, can't insert log
echo "domain no exist log"
else
echo "other log and exit: $logStr"
exit 0
fi
# get sender
# the exrep must have (),and all must escape
sender=`expr "$logStr" : '.*from\=<\([a-zA-Z0-9_\.]\+\)@[a-zA-Z0-9_\.]\+>'`
if [ -z "$sender" ]; then # get null exit 0
echo 'log can not find email and exit'
exit 0
fi
echo "line have email user name : $sender"
letterId=`expr "$sender" : '.*_\([0-9]\+\)$'`;
if [ -z "$letterId" ]; then
echo 'can not found letter DBid in user name exit
it must like:
username_xx_yy_12345@domain
the last _ concat a letter db id number'
exit 0
fi
echo "letter DBid = $letterId"
if [ ! -e "$logPath" ];then
if [ ! -w "$shDir" ];then
echo "$shDir permission denied for create dir and exit, run sh install"
exit 0
fi
mkdir $logPath
echo "create path : $logPath"
elif [ ! -d "$logPath" ];then
echo "$logPath is exist but no a dir exit"
exit 0
fi
if [ ! -w "$logPath" ] || [ ! -r "$logPath" ] || [ ! -x "$logPath" ]; then
echo "$logPath permission denied for create file exit, run sh install, it must be read/write/run"
exit 0
fi
if [ -e "$logPath/$letterId" ] ;then
echo "file exist"
if [ ! -w "$logPath/$letterId" ] || [ ! -r "$logPath/$letterId" ] || [ ! -x "$logPath/$letterId" ]; then
echo "$logPath/$letterId permission denied for write exit, run sh install, it must be read/write/run"
exit 0
fi
echo $logStr >> "$logPath/$letterId" # auto create file and add log
else
echo $logStr > "$logPath/$letterId"
`chmod 707 $logPath/$letterId`
echo "file no exist:create it and chmod to 707"
fi
echo "add log [$logPath/$letterId] exit"
exit 0 #must
===============================脚本逻辑说明================
增加了安装自动设置目录权限功能
在rsyslog的配置文件(/etc/rsyslog.d/50-default.conf)配置rsyslog把所有的mail.*日志转发到savePostfixLog.sh上.
配置方式:
$template mailFormat,"%msg%"
mail.* ^/var/www/edm/sh/savePostfixLog.sh;mailFormat
然后sh把错误的信息分选保存到文件中,因为前面修改过postfix的代码,已经让每个出错记录行带上发件人,而发件人中带有信件数据库id,这样解析发件人即可关联到信件,把每封信的出错信息保存到一个文件中,这样有利于数据分析,因为做为群发,发件人无所谓.只要是统计,详细分出域名出/用户不存在/挨拒收==的投递出错信息即可.
注意的事项是:
1 rsysylog调用本sh时,使用了跟rsyslog相同的用户,所以需要考虑这个用户的权限,防止目录写的权限不足导致日志写错误
2 在编写时,可以信用rsyslog守护进程,然后启用debug进程,rsyslogd -n,结束它时,使用kill -9 rsyslogd_PID