我的个人网站项目托管在osc的git仓库里,以前的更新方法是从把代码从本地push到git仓库后,远程登陆服务器,执行一次git pull,把代码更新到服务器。
久而久之,渐渐觉得这样的方式太过麻烦,我知道git仓库一般都提供web hooks, 就是每次push代码后,都会给远程HTTP URL发送一个POST请求,比如这是oschina的:http://git.oschina.net/oschina/git-osc/wikis/WebHook-%E4%BD%BF%E7%94%A8%E7%AE%80%E4%BB%8B 。 所以方法是服务器收到这个post请求之后在网站目录自动执行一次git pull, 这样就把代码更新到服务器了。

但是有一个问题,服务器使用的是php,获取这个请求之后,由于php-fpm用户为daemon,因为安全因素,网站目录对这个用户并不全部可写,所以执行git pull需要root权限,而且,使用system(),exec(),passthru()这类调用外部程序的函数有一定的危险,我不喜欢。

然后找到了一个神器:inotify tools,关于它的介绍可以参考这两篇文章:

How to use inotify-tools to trigger scripts on filesystem events

Inotify: 高效、实时的Linux文件系统事件监控框架

我的想法是:用Inotify监控指定目录,是php接收到web hook post请求后,向这个目录或文件写入内容,Inotify监测到文件变化后执行git pull完成更新。

安装可以参考wiki , 在centos上执行

yum install inotify-tools

即可,注意Linux kernel 至少要达到 2.6.13 。

安装之后,把下面的内容保存为inotify.sh,并且chmod +x inotify.sh,这是我们的监控脚本, 内容中/websites/cellmean/src/ 是要更新的代码所在的目录, /websites/cellmean/src/wp-content/uploads/git 是我们要监控的目录,后面会说明,脚本主要参考这篇文章:http://www.tiyee.net/post/193

#!/bin/bash
WAIT_DIR=${1-/websites/cellmean/src/wp-content/uploads/git}
inotifywait -qme modify,move,create $WAIT_DIR --format '"%w" "%f" "%e" "%T"' --timefmt='%F_%T' \
        | while read DIR FILE EVENT TIME ;do

        echo $DIR $FILE $EVENT $TIME
        #eval "str=${FILE}"
        dir="/websites/cellmean/src/"
        cd $dir
        git pull

done
 

接下来我们只要接到post请求后向监控的目录,也就是前文的/websites/cellmean/src/wp-content/uploads/git 写入文件即可,网站是wordpress的,于是我又写了一个插件来干这件事,这是下载链接: falcon-git

激活插件后,在osc git网页中添加web hook设置,URL填写:http://你的wordpress主页/?from=git ,密码请自己设置一个,后面要用到,比如这样:

bbb

然后回到插件设置页面,把刚才设置的密码填入,分支请填写服务器部署用的分支,这个选项的作用是当该分支上push更新了才会自动部署, 默认使用master,上图:

falcon-git

保存后,在服务器执行刚才的监控脚本。

nohup /path/to/inotify.sh >> /path/to/log/git.log 2>&1 &

这样就大功告成了,以后只要本地执行git push之后,服务器就能自动部署了,是不是很方便。哈哈。

这是我这两天的更新历史,看着这些记录还挺有成就感的

- EOF -