前一阵子我其实是想用 Google drive + incron 的方式自动提交博客,然而碰到了一些问题,Goole drive 可以同步文件夹,但不能自动同步文件夹,并且没有 git 这样优秀的版本控制。 而我又不想自己手动上传文章以及拉取文章,拉取之后还得手工 hexo g,太麻烦了。 写定时拉取,自动更新的确可以,但是这样太没逼格了。 于是我就查资料,发现了 git 有 webhooks。
什么是 Webhooks
先放几个官方的说明:
简单概括一下(译自 Github Webhooks):
- Webhooks 允许我们建立关于项目的在 GitHub 上的事件集成。当事件触发的时候,会通过 HTTP POST 的方式,向我们的服务器发送请求。我们可以用这个服务器去更新外部跟踪,触发 CI build,更新备份镜像,部署到生产服务器.
- 每个 Webhook 都可以安装在一个项目或者组织上,安装完毕之后,就可以随着订阅的时间进行触发.
- 每个项目的每个事件最多可以安装 20 个 Webhook.
Webhooks 脚本
Webhook 脚本实现可以用 PHP、NodeJS 等,本文仅介绍 PHP 脚本,笔者也用的这个脚本
<?php
// 本地仓库路径
$local = '/var/www/html/';
// 安全验证字符串,为空则不验证
$token = '123456';
// 如果启用验证,并且验证失败,返回错误
$httpToken = isset($_SERVER['HTTP_X_GITLAB_TOKEN']) ? $_SERVER['HTTP_X_GITLAB_TOKEN'] : '';
if ($token && $httpToken != $token) {
header('HTTP/1.1 403 Permission Denied');
die('Permission denied.');
}
// 如果仓库目录不存在,返回错误
if (!is_dir($local)) {
header('HTTP/1.1 500 Internal Server Error');
die('Local directory is missing');
}
//如果请求体内容为空,返回错误
$payload = file_get_contents('php://input');
if (!$payload) {
header('HTTP/1.1 400 Bad Request');
die('HTTP HEADER or POST is missing.');
}
/*
* 这里有几点需要注意:
*
* 1.确保 PHP 正常执行系统命令。写一个 PHP 文件,内容:
* `<?php shell_exec('ls -la')`
* 在通过浏览器访问这个文件,能够输出目录结构说明 PHP 可以运行系统命令。
*
* 2、PHP 一般使用 www-data 或者 nginx 用户运行,PHP 通过脚本执行系统命令也是用这个用户,
* 所以必须确保在该用户家目录(一般是/home/www-data 或/home/nginx)下有.ssh 目录和
* 一些授权文件,以及 git 配置文件,如下:
* ```
* + .ssh
* - authorized_keys
* - config
* - id_rsa
* - id_rsa.pub
* - known_hosts
* - .gitconfig
* ```
*
* 3.在执行的命令后面加上 2>&1 可以输出详细信息,确定错误位置
*
* 4.git 目录权限问题。比如:
* `fatal: Unable to create '/data/www/html/awaimai/.git/index.lock': Permission denied`
* 那就是 PHP 用户没有写权限,需要给目录授予权限:
* ``
* sudo chown -R :www-data /data/www/html/awaimai`
* sudo chmod -R g+w /data/www/html/awaimai
* ```
*
* 5.SSH 认证问题。如果是通过 SSH 认证,有可能提示错误:
* `Could not create directory '/.ssh'.`
* 或者
* `Host key verification failed.`
*
*/
echo shell_exec("cd {$local} && git pull 2>&1");
die("done " . date('Y-m-d H:i:s', time()));
Webhooks 配置
像图片中这样设置就可以了
注意事项
如果不能正常的拉取,你可以先使用下面的 php 程序进行测试。
<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>
如果网页不能够输出你当前的文件夹下的文件,说明 shell_exe() 函数被禁用了,你需要修改 php.ini,启用该函数
然后用下面的 php 程序接着测试
<?php
// 本地仓库路径
$local = '/var/www/html/';
echo shell_exec("cd {$local} && git pull 2>&1");
die("done " . date('Y-m-d H:i:s', time()));
?>
看看输出的信息。在执行的命令后面加上 2>&1 可以输出详细信息,确定错误位置。
一般情况下有 3 种错误:
- 权限不足
- ssh 认证错误
- 不能读写文件
对于权限不足,你需要给网站 www 或则 nginx 用户组权限,不是 777 这样的权限,因为 PHP 一般使用 www 或者 nginx 用户运行,PHP 通过脚本执行系统命令也是用这个用户。一般可以用下面的命令解决,具体还是要看你的环境:
sudo chown -R www:www /data/www/
sudo chmod -R g+w /data/www/
对于 ssh 认证错误,你需要保证 www 或则 nginx 用户组的文件夹下有.ssh 目录(一般是/home/www 或/home/nginx)和一些授权文件,以及 git 配置文件,如下:
+ .ssh
- authorized_keys
- config
- id_rsa
- id_rsa.pub
- known_hosts
- .gitconfig
而且你需要在 Github、Gitlab、Gitee 中加入你的公钥。具体你可以百度谷歌一下。 输入下面的命令就可以了
ssh-keygen -t rsa
参考资料&转载来源
部分内容是转载自: Github、GitLab、Gitee 使用 Webhooks 实现代码自动部署 其他优秀参考资料: gitlab 利用 webhook 自动部署代码 利用 GitLab 的 Webhooks 功能,实现网站代码自动更新部署 给你的项目增加 Webhooks,自动进行部署(包含 Github/Gitlab) 使用 Gitlab Webhooks 自动部署代码 使用 GitHub / GitLab 的 Webhooks 进行网站自动化部署 git webhooks 实现自动拉取代码 利用 WebHook 实现 PHP 自动部署 Git 代码 使用 Git 的 Webhooks 进行服务器自动部署代码 使用 Github 的 webhooks 进行网站自动化部署