shell脚本:扫描列表文件并执行

脚本一:

   需求:

       1、扫描WEB后台成生文件目录中含有可执行脚本路径内容的文件,执行后删除。

       2、计划任务周期:每分钟。

#!/bin/bash
# date:     20140213
# function: 扫描任意目录中的普通文件,执行该文件中的每一行php或其它脚本文件(保证每行一个绝对路径的文件)。
PATH=/bin:/sbin:/usr/bin:/usr/sbin
IFS='
'
export PATH IFS
# web后台生成文件的目录
listf_d="/data/web/adp.qq.com/application/logs/handshell"
# 执行成功或失败的日志文件。
log="/data/logs/cronlog/scanphp/shell-scanphp.log"
# php执行失败时保存php的错误输出,用于debug。
php_log="/data/logs/cronlog/scanphp/shell-scanphp.error_log"
# 该文件用于防止新的计划任务执行相同的文件中的内容。
lock="/var/run/shell-scanphp.lock"
t="date +%F-%T"
php_bin="/usr/local/php-5.2.14/bin/php"

if [ ! -d "$(dirname ${log})" ];then
        mkdir -p $(dirname ${log})
fi

if [ ! -d "$(dirname ${php_log})" ];then
        mkdir -p $(dirname ${php_log})
fi

if [ ! -d "$listf_d" ];then
    echo "$($t):$PPID-$$ ERROR: Dir "$listf_d" not exsit." >> "$log"
    exit 1
else
    cd "$listf_d"
fi

listf=$(ls | cat)
if [ -z "$listf"  ];then
    exit 0
fi
if [ ! -f "$lock" ];then
    touch "$lock" &>/dev/null
    rc=$?
    if [ $rc -ne 0 ];then
        echo "$($t):$PPID-$$ ERROR: Can't create lock file "$lock"." >> "$log"
        exit 11
    fi
fi
for listf_f in $(echo $listf)
do
    grep -q "$listf_f" "$lock"
    rc=$?
    if [ $rc -ne 0 ];then
        if [ -f "$listf_f" -a -s "$listf_f" ];then
            #上锁
            echo "$listf_f" >> "$lock"
            #程序人员生成的文件只有一行路径,且无换行符,如果有换行符,可以删除以下4行。
            linenum=$(wc -l "$listf_f" |cut -d " " -f1)
            if [ "$linenum" -eq "0" -a -s "$listf_f" ];then
                echo >> "$listf_f"
            fi
            while read line
            do
                if [ -f "$line" ];then
                    "$php_bin" "$line" 2>> "$php_log" >/dev/null
                    rc=$?
                    if [ $rc -eq 0 ];then
                        echo "$($t):$PPID-$$ INFO: $line exec sucess." >> "$log"
                    else
                        echo "$($t):$PPID-$$ ERROR: $line exec error." >> "$log"
                    fi
                else
                    #加判断,防止空行被视为无效的脚本文件写入日志。
                    if [ -n "$line" ];then
                        echo "$($t):$PPID-$$ ERROR: php file($line) not exsit." >> "$log"
                    fi
                fi
            done < "$listf_f"
            #遍历完一个文件的行后删除后台生成的文件,再清除锁文件中对应的记录。
            rm ./"$listf_f"
            sed -i "/$listf_f/d" "$lock"
        else
            #加判断防止误报上一次计划任务删除的文件为无效的后台生成文件。不做删除操作,用于debug。
            if [ -e "$listf_f" ];then
                echo "$($t):$PPID-$$ ERROR: "$listf_d/$listf_f" is a invalid generate file." >> "$log"
            fi
        fi
    else
        #上一次计划任务还未执行完该文件,跳过。
        echo "$($t):$PPID-$$ NOTICE: "$listf_d/$listf_f" in process and skipped." >> "$log"
    fi
done

注:

   该脚本对于后台产生的文件中有多个需要长时间才能执行完的脚本路径时效率不高,因为一个计划任务只要开始执行时,就会把该后台产生的文件加入lock。

   如果真是这样,使用该shell脚本可以考虑生成多个文件,或改脚本为多进程执行单个文件,注意重复执行的问题。


脚本二(脚本一更具通用性,脚本二只针对本公司特殊要求定制):

   需求二:

       1、web后台产生文件的目录确定一行一个路径(无换行符)。

       2、执行后台文件中的内容后不管成功不成功立马删除该后台文件。

       3、计划任务周期:每分钟。

   分析:

       shell作为一门过程语言只能一条一条的自上而下执行,因为本功能写入日志还要判断是否执 行成功,所以不能放入后台"&"后再执行删除源文件,所以,可以通过先判断后台文件中的路径是否可执行,如果可以执行先保存到变量,然后删除文件,然后再由php命令执行该变量来解决。

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin
IFS='
'
export PATH IFS
listf_d="/data/web/adp.qq.com/application/logs/handshell"
log="/data/logs/cronlog/scanphp/shell-scanphp.log"
php_log="/data/logs/cronlog/scanphp/shell-scanphp.error_log"
t="date +%F-%T"
php_bin="/usr/local/php-5.2.14/bin/php"

if [ ! -d "$(dirname ${log})" ];then
        mkdir -p $(dirname ${log})
fi
if [ ! -d "$(dirname ${php_log})" ];then
        mkdir -p $(dirname ${php_log})
fi

if [ ! -d "$listf_d" ];then
    echo "$($t):$PPID-$$ ERROR: Dir "$listf_d" not exsit." >> "$log"
    exit 1
else
    cd "$listf_d"
fi

listf=$(ls | cat)
if [ -z "$listf" ];then
    exit 0
fi
for listf_f in $(echo $listf)
do
    if [ -f "$listf_f" -a -s "$listf_f" ];then
        exec_f="$(sed '1q' $listf_f)"
        if [ -f "$exec_f" ];then
            rm ./"$listf_f"
            start_t=$(date +%s)
            "$php_bin" "$exec_f" 2>> "$php_log" >/dev/null
            rc=$?
            stop_t=$(date +%s)
            if [ $rc -eq 0 ];then
                use_t=$(($stop_t-$start_t))
                echo "$($t):$PPID-$$ INFO: $exec_f exec sucess(${use_t}s)." >> "$log"
            else
                echo "$($t):$PPID-$$ ERROR: $exec_f exec error." >> "$log"
            fi
        else
            if [ -n "$exec_f" ];then
                echo "$($t):$PPID-$$ ERROR: exec file($exec_f) not exsit." >> "$log"
            fi
        fi
    else
        if [ -e "$listf_f" ];then
            echo "$($t):$PPID-$$ ERROR: "$listf_d/$listf_f" is a invalid generate file." >> "$log"
        fi
    fi
done



脚本三:20140806

要求:5秒执行一次,之前的脚本,计划任务无法满足。

分析:不考虑开机启动,使用计划任务。使用该脚本时根据要扫描的列表文件和执行数量设定(一般无问题,每个php执行语句直接放后台)。每分钟执行11次。

脚本:添加了php标准输出到日志,删除3天前的日志。


#!/bin/bash
#$0: scan_file_exec_php.sh
#Date: 20140806 v1.1

PATH=/bin:/sbin:/usr/bin:/usr/sbin
#直接按空格、TAB、回车
IFS='     
'
export PATH IFS
listf_d="/data/web/ads.xywy.com/application/logs/handshell"
log_d="/data/logs/cronlog/scanphp"
log="$log_d/scan_file_exec_php.sh.log"
t="date +%F-%T"
php_bin="/usr/local/php-5.2.14/bin/php"
count=0


if [ ! -d "$log_d" ];then
        mkdir -p "$log_d"
fi

find /data/logs/cronlog/scanphp -maxdepth 1 -type f -name '*.log' -mtime +3 -delete
>$log

if [ ! -d "$listf_d" ];then
    echo "$($t):$PPID-$$ ERROR: Dir "$listf_d" not exsit." >> "$log"
    exit 1
else
    cd "$listf_d"
fi
 
while true
do
    ((count++))
    if [ $count -eq 13 ];then
        break
    fi
    
    listf=$(ls | cat)
    if [ -z "$listf" ];then
        sleep 5
        continue
    fi

    for listf_f in $(echo $listf)
    do
        if [ -f "$listf_f" -a -s "$listf_f" ];then
            exec_f="$(sed '1q' $listf_f)"
            rm ./"$listf_f"
            if [ -f "$exec_f" ];then
                "$php_bin" "$exec_f" > "$log_d/`basename ${exec_f}`_$($t).log" 2>&1 &
                echo "$($t):$PPID-$$ INFO: \"$exec_f\" in \"$listf_f\" executed." >> "$log"
            else
                if [ -n "$exec_f" ];then
                    echo "$($t):$PPID-$$ ERROR: \"$exec_f\" in \"$listf_f\" not exsit." >> "$log"
                fi
            fi
        else
            if [ -e "$listf_f" ];then
                echo "$($t):$PPID-$$ ERROR: "$listf_d/$listf_f" is a invalid generate file by php." >> "$log"
            fi
        fi
    done

    sleep 5
done


你可能感兴趣的:(shell脚本:扫描列表文件并执行)