博客维护脚本

我博客维护脚本的功能主要:启动、停止博客(MySQL、PHP-FPM、Nginx),数据库数据和访问日志打包备份、Wordpress的文件打包备份、把恶意扫描的IP加入防火墙黑名单、过滤出人类访问的记录。

我的VPS的系统是Ubuntu 12.04。

启动、停止博客脚本

startBlog.sh,这个脚本还加到开机启动脚本里,万一VPS重启了也会自动启动博客。

log=/home/coderbee/blog/startBlogLog.log
date >> $log
/usr/share/mysql/bin/mysql.server start && {
        /usr/share/php5/sbin/php-fpm && {
                /usr/share/nginx/sbin/nginx && echo "start blog ok" >> $log ||
                echo "start nginx failed " >> $log ;
        };
} || { echo "start mysql failed ."  >> $log ; }

shutDownBlog.sh,这个脚本主要是在刚开始搭建博客时用,现在基本不用。

/usr/share/mysql/bin/mysql.server stop 2>&1 >/dev/null
kill -quit `cat /usr/share/php5/var/run/php-fpm.pid` 2>&1 >/dev/null
/usr/share/nginx/sbin/nginx -s stop 2>&1 >/dev/null

数据库数据和访问日志打包备份

cronday.sh,这个脚本每天凌晨调度执行。

export JAVA_HOME='/usr/share/jdk1.7.0_21'
export PATH=$PATH:$JAVA_HOME/bin

blog=/home/coderbee/blog/
bakDir=${blog}dataBak
#  用mysqldump命令把博客的数据库导出来,然后用vpsBack.jar上传的Dropbox,vpsBack.jar是用Dropbox的API写的一个小工具,只有简单的上传功能。
/usr/share/mysql/bin/mysqldump -u wpblog -p'password' blog > ${bakDir}/blog-bak.sql.tmp 2>/dev/null &&
 mv ${bakDir}/blog-bak.sql.tmp ${bakDir}/blog-bak.sql  &&
 java -jar ${blog}vpsBack.jar upload vpsBak4coderbee/db/`date -d"yesterday" +"%Y%m%d"`/ ${bakDir}/blog-bak.sql &&
 echo "backup sql to dropbox ok ."


#  一个月的访问日志放在以月份命名的文件夹下,同一年的月份的文件夹放在以年命名的文件夹下。
monDir=${bakDir}/weblog/$(date -d"yesterday" +"%Y")/$(date -d"yesterday" +"%m")
dayPath=$(date -d"yesterday" +"%d").log
[ -d "${monDir}" ] || mkdir -p ${monDir}


logDir=/usr/share/nginx/logs

#  nginx日志拷贝、清理、切换
cd $logDir && cp access.log ${dayPath} && :> access.log &&
#  通知nginx重新打开日志文件
kill -USR1  `cat /usr/share/nginx/logs/nginx.pid` &&


#  打包访问日志
tar -czf "${dayPath}.tar.gz" "${dayPath}" &&

#  备份访问日志
rm -f ${dayPath} && mv -f "${dayPath}.tar.gz" ${monDir} &&
chown -R coderbee:appgroup ${bakDir} && echo "backup web log down"

WordPress的文件打包备份

cronweek.sh,这个脚本会打包Wordpress的文件,并上传到Dropbox。因为写博客上传的多媒体和Wordpress插件一般会放在这个目录下,所以每周备份一次。

cd /var/www/

export JAVA_HOME="/usr/share/jdk1.7.0_21"
export PATH=$PATH:$JAVA_HOME/bin

fname="web-`date +"%Y%m%d" -d"yesterday"`.gz"
tar czf $fname wordpress/ && 
 java -jar /home/coderbee/blog/vpsBack.jar upload vpsBak4coderbee/web/ $fname &&
 rm $fname && echo "backup web done ."

过滤出人类访问的记录

先说下我的nginx的日志记录格式:
'$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';

比如这是一条:
122.194.20.145 - - [03/Aug/2013:18:13:49 +0800] "GET /index.php/algorithm/20130801/343 HTTP/1.1" 200 10575 "http://news.dbanotes.net/newest" "Mozilla/5.0 (iPad; CPU OS 6_0_2 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A550 Safari/8536.25" "-"

这个只是很简单的日志处理脚本,只处理今天的博客文章和首页的访问日志,根据User-Agent过滤。

log="/usr/share/nginx/logs/access.log"

awk -F"\"" '$2 ~ /(GET \/ HTTP.*)|(\/index.php\/[a-zA-Z]*\/[0-9]+\/[0-9]+ .*)|(\/html5\/[a-zA-Z0-9]+.html .*)/ && $6 !~/(http:\/\/|Java|robot|.com|Wget|PHP|Reeder|Spider|(^-$)|ips-agent|@)/ {print $0}' $log

还有按refer统计:
. humanVisit.sh | awk -F"\"" '{print $2, $4}' | cut -d" " -f2,4 | sort -k 1 | uniq -c

访问最多的url:
. humanVisit.sh | awk -F"\"" '{print $2}' | cut -d" " -f2 | sort | uniq -c

把恶意扫描的IP加入防火墙黑名单

这个脚本是最近添加的,主要是把那些访问日志里4xx状态、访问的URL看起来是恶意的IP加入防火墙过滤掉。由cron没小时调度执行一次。

ipfilter.sh

cd /home/coderbee/blog/
sortIps=sortIpx

#  过滤出访问日志里4xx状态、访问的URL里包含 admin|Admin|scripts且以php后缀结尾的IP
awk -F'"' '$3~/4.. [0-9]+/ && $2 ~ /GET \/.*(admin|Admin|scripts).+(index|setup)\.php/ {print $0}' /usr/share/nginx/logs/access.log | awk '{print $1}' >> evilIP

sort evilIP | uniq > evilIP.tmp && mv evilIP{.tmp,}

iptables -F INPUT

#  把整个IP/24段加入黑名单
cut -d. -f1-3 ips evilIP | sort | uniq > $sortIps
for i in $sortIps
do
    while read line
    do
        if [[ ! -z $line ]]; then
           ip=$line/24
           iptables -t filter -I INPUT -s $ip -j DROP
        fi
    done < $i
done

rm $sortIps

cron调度

1  0  *   *  * /home/coderbee/blog/cronday.sh 2>&1 >> /home/coderbee/blog/cronlog
1  4  *   *  1 /home/coderbee/blog/cronweek.sh 2>&1 >> /home/coderbee/blog/cronlog
1  *  *   *  * /home/coderbee/blog/ipfilter.sh 2>&1 >> /home/coderbee/blog/ipfilterlog

小结

这里并没有复杂高深的东西,基本都是 AWK处理文本、sort排序、uniq去重、cut筛选字段、tar进行打包压缩、用cron定时调度,还用了shell的命令条件执行、命令组合、重定向等。

这也体现这Linux系统强大之一:提供大量简单的基本命令,用shell把这些命令粘合起来就可以实现更复杂、强大的功能。

我也会继续探索Linux shell的更多玩法,尽可能让手工操作转为自动化的。

要Linux下编辑shell,首先要掌握一个命令行下的文本编辑器,一般就是Vi了,我之前是按照 酷壳的这篇文章 《简明 Vim 练级攻略》 http://coolshell.cn/articles/5426.html,练了两个星期才基本上上手。

关于博客搭建过程可见: http://coderbee.net/index.php/notes/20130620/254

后续

20130810:前面的日志统计脚本 .humanVisit 仍然需要其他命令来处理,刚才把awk实现了那些功能,就简单多了:

#!/bin/bash

log="/usr/local/nginx/logs/access.log"

awk -F"\"" '$2 ~ /(GET \/ HTTP.*)|(\/index.php\/[a-zA-Z]*\/[0-9]+\/[0-9]+ .*)|(\/html5\/[a-zA-Z0-9]+.html .*)/ && $6 !~
/(http:\/\/|Java|robot|.com|Wget|PHP|Reeder|Spider|(^-$)|ips-agent|@|Python|bot|NING)/ {
    if ( $4 ~ /http[s]*:\/\// ){
        if ( $4 ~ /http:\/\// ){
                refer=substr($4, 8)
        } else {
                refer=substr($4, 9)
        }
        refer=substr($4, 8)
        refer=substr(refer, 1, index(refer, "/") - 1)
        refers[refer]++
    } else {
        refers[$4]++
    }

    paper=substr($2, 5)
    paper=substr(paper, 1, index(paper, " ")-1)
    papers[paper]++
}

function printStatistic(msg, arr) {
    sum=0
    printf ("%s\n", msg)
    for (i in arr) {
        sum+=arr[i]
        printf("%6d   %s\n", arr[i], i) | "sort"
    }
    close("sort")
    printf ("total count: %d\n", sum)
}

END {
    printStatistic("visit refers:", refers)
    print ""
    printStatistic("visit papers:", papers)
}
' $log

用到了AWK的不少东西,效果不错。


欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。

博客维护脚本》上有6个想法

  1. 几个疑问不明白:
    1. ipfilter.sh里面的
    cd /home/coderbee/blog/
    sortIps=sortIpx

    2. humanvisit.sh怎么用?
    在我机器上报错,第二行

    • 博主,可否将ipfilter.sh描述详细一点,无法移植到我机器上去啊?
      另外我的一个脚本在我机器上执行是我的,在VPS上就有问题,为什么啊?
      说找不到本地目录下的一个文件,但是确实是存在啊!

      • 哦,报什么文件找不到啊? evilIP和ips都是我本地的文件,里面就是一行一行的要过滤掉ip地址。 iptables -F INPUT 是清除现有iptables的设置,iptables -t filter -I INPUT -s $ip -j DROP就是删除$ip的包。

        你可以先一条一条命令测试,慢慢地把所有命令加上去。

    • 是因为我的脚本都放在/home/coderbee/blog/ 目录下,sortIps=sortIpx 这里只是定义一个临时文件的名字,直接写文件名也可以的。

      humanvisit.sh的第二行是指 log=”/usr/local/nginx/logs/access.log” 吧,这是我的nginx日志的路径。因为这路径可能多次使用,赋值给变量简单点,放在脚本开始处是方便修改。

      • 博主,
        咨询几个问题:
        1. 站点遭到广告轰炸了,留言都是广告,如何屏蔽?
        2. sortIps=sortIpx 这个是个本地文件?存储形式是什么?在我vps上执行./ipfilter.sh无法执行,提示
        cut: ips: No such file or directory
        3. 在我本地Ubuntu机器上测试好了上传备份的upload.sh脚本,还有个config的文件,也是个shell脚本,里面是一些配置信息。我在本地电脑执行./upload.sh是没有问题的,但是在vps上就有问题,提示找不到config这个文件,我备份是备份到腾讯的云平台去,结果失败了,一直没找到原因!
        Thanks

        • 广告轰炸,我也经常碰到,我直接加到 evilIP文件里,这是3条举例:
          110.85.124.128
          110.85.124.143
          110.85.125.64
          然后执行ipfilter.sh脚本,你可以看到,我是整个ip段过滤掉的。PS:ips里的存储形式也是上面的这样的,一行一条ip。ips里存放的是一般的,就是垃圾广告的,evilIP里的是扫描我的VPS的恶意IP。

          sortIps=sortIpx 定义了一个变量,cut -d. -f1-3 ips evilIP | sort | uniq > $sortIps 这里是取每个IP的以句点分隔的前三段,比如110.85.124,然后排序、去重,再写到$sortIps,也就是名为sortIpx的文件,不用变量,直接写文件名也行。这些都是基础的东西。

          备份的话,我最近用Go写了个Dropbox的sdk,然后用这个sdk写了个应用,你可以看这篇文章: http://coderbee.net/index.php/go/20130829/427 ,用Go的好处是编译成一个可执行文件,不需要配置依赖库什么的。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据