使用git webhook实现代码自动部署
需求来源于最近准备做一款区块链交易系统的应用,本地编码,服务器运行调试,来回频繁切换效率地,费时间,所以就有了自动部署的需求。
折腾了大半天,终于搞定了git的自动部署。中间踩过的坑遇到记录一下,不详细讲解了,容易误导他人。
第一步:部署docker,安装lnmp。基本按照这一篇实现:https://www.jianshu.com/p/34a625621a9a
注意事项:
其一:
文中第三步:
[root@b1fc5ed806d1 /]# wget http://soft.vpser.net/lnmp/lnmp1.5.tar.gz -cO lnmp1.5.tar.gz && tar zxf lnmp1.5.tar.gz && cd lnmp1.5 && ./install.sh lnmp
lnmp1.5.tar.gz的版本安装屡次失败,改为lnmp1.7.tar.gz。猜测测试centos版本跟lnmp版本不适应导致的。【不重要,如果遇到失败,可以试试其他版本】
其二docker-compose.yml配置。
version: '3.3' services: coins: image: 'jiangtian2020/lnmp:1.0' ports: - '7777:80' - '8888:8080' expose: - 80 - 8080 - 8081 - 8082 environment: TZ: Asia/Shanghai tty: 'true'
简单配置即可,无需太复杂。文档:https://deepzz.com/post/docker-compose-file.html#toc_5
配置不难,仔细阅读一遍,一般没有依赖容器,没有共享网络等,无需过深研究这个配置。因为我是lnmp集成环境,都装了,所以无需依赖,也无需共享其他网络。
其三问过运维同事:
第二步:git--webhook配置回调地址:
配置教程参考:https://www.weipxiu.com/4103.html
自动部署代码(php版)
`<?php
/**
- Created by PhpStorm.
- Author: jt
- Date: 2020/6/6
- Time: 上午9:53
- E-Mail: tibertwater@gmail.com
- QQ: 284053253
*/
ini_set('display_errors', 'On');
error_reporting(E_ALL);
//git webhook 自动部署脚本
$requestBody = file_get_contents("php://input"); //该方法可以接收post传过来的json字符串
defined("LOG_DIR") or define("LOG_DIR", "/home/wwwroot/coins/App/Runtime/Logs/Git/");
defined("SRC_DIR") or define("SRC_DIR", "/tmp/coins");
defined("DES_DIR") or define("DES_DIR", "/home/wwwroot/coins");
if (empty($requestBody)) { //判断数据是不是空
die('send fail');
}
$content = json_decode($requestBody, true); //数据转换
if (!$content) parse_str(urldecode($requestBody), $content);
$content = json_decode($content['payload'], true);
//若是主分支且提交数大于0
if ($content['ref'] == 'refs/heads/master') {
file_put_contents(LOG_DIR . "git-webhook.log", "写入日志" . PHP_EOL, FILE_APPEND);
//PHP函数执行git命令
/**$bool = chdir(SRC_DIR);
if ($bool === false) {
die("Could not chdir()");
}*/
//$re = shell_exec("ls -al");
$res = shell_exec('chmod -R 777 /tmp/coins;cd /tmp/coins;git reset --hard origin/master && git clean -f && git pull 2>&1 && git checkout master;');
$dir = getcwd();
file_put_contents(LOG_DIR . "git-content.log", "当前目录:{$dir}" . PHP_EOL, FILE_APPEND);
file_put_contents(LOG_DIR . "git-content.log", $res . PHP_EOL, FILE_APPEND);
file_copy(SRC_DIR, DES_DIR);
$res_log.= ' 在' . date('Y-m-d H:i:s') . '向' . $content['repository']['name']
. '项目的' . $content['ref'] . '分支push' . $res . PHP_EOL;
//将每次拉取信息追加写入到日志里
file_put_contents(LOG_DIR . "git-webhook.log", $res_log, FILE_APPEND);
}
function file_copy($src, $dst) {
$dir = opendir($src);
if (!file_exists($dst)) mkdir($dst);
while (false !== ($file = readdir($dir))) {
if (($file != '.') && ($file != '..') && $file != '.git') {
if (is_dir($src . '/' . $file)) {
file_copy($src . '/' . $file, $dst . '/' . $file);
} else {
copy($src . '/' . $file, $dst . '/' . $file);
}
}
}
closedir($dir);
}
`
其中有几个重大的坑:
其一:shell_exec在执行命令的时候,cd始终没有反应,最终追查来追查去,是因为lnmp中nginx的fastcgi.conf中加了个参数:
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/:/home:/tmp/coins";
它限定了可访问的目录。导致我指定的目录始终无权限,以上是我修改过的参数。
其二:php的函数chdir是同样问题。
第三:以上问题解决完,进入测试自动部署阶段。可是测来测去,始终报一个错误:
fatal: could not read Username for 'https://github.com': No such file or directory?
该问题出现的原因是我是在root下做的所有操作,但是nginx及php用户是www,用户组是www,怀疑是权限问题,但chown或者chmod777都不可以。
后来找到一种说法,说是用ssh,服务器跟git建立起公私钥配对。
便试着操作了下:
在root下,更改仓库.git/configx下的url。
然后git pull会自动要求生成公私钥,或者用ssh-keygen -t rsa -C 'abc@xxx.com' (git邮箱)
在git配置ssh公钥:
并且将id_rsa.pub中的字符串粘贴到git去。
以为大功告成?一运行,提示:
Host key verification failed. fatal: Could not read from remote repository.
啥原因?因为我的公钥是root账户下生成的,而非nginx,php账户,所以得给它生成一个。 usermod -s /bin/bash www,让php,nginx账户成为一个普通账户。按以上步骤进行一遍。再运行,大功告成。