rsyslog + postfix 把postfix调用rsyslog生成的mail日志转向给自己处理的处理脚本+配置

来源:互联网 发布:java中变量类型 编辑:程序博客网 时间:2024/06/15 20:28

=============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