time 2020-05-15
author Venki
theme 本篇博文主要目的是:将自己部署的gitlab代码管理系统,实现本地提交和服务器自动更新,希望可以帮助到和我一样有需求的小伙伴们。
statement 本篇博文在借鉴他人文章的基础之上进行重新修改,虽然其中磕磕绊绊遇到许多问题,但好在一一都解决了,感谢这篇文章说说配置gitlab的webhook时踩过的坑
有话先说
- 关于gitlab
之前已经部署gitlab,并且可以正常使用,之前我的博文有写到关于本地部署gitlab的详细文章,有意者请查看Linux-安装-Gitlab
- 关于git
Linux服务器已经安装了git工具,git的安装,再简单不过,请自行百度!
- 关于环境
我用的是centOs nginx 以及php环境实现的,但是钩子这东西,其实就是一个接口,所以,不管什么语言,其实原理都是一样的。
- 关于PHP和nginx的安装我的博客也有文章写过,请自行查阅Linux-安装-PHP、Linux-安装-Nginx
正文开始
1. 业务场景
- 为了方便管理,用公司一台服务器自行搭建了gitlab用来管理代码,Windows上面开发,然后提交到gitlab之后,服务器代码自动更新。
2. 逻辑介绍
- 提交(git push)时刻,触发钩子,钩子执行相应程序,拉取分支代码,实现自动更新
3. 编写钩子
- 其实就相当于一个接口地址,只要gitlab可以调通就行
- 配置一个nginx站点,并且可访问即可
server {
listen 5698; # 端口
server_name 192.168.1.xxx; # IP地址
root /home/app/hooks; # 钩子脚本所在目录
location / {
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?$query_string;
autoindex on;
}
# 关闭 [/favicon.ico] 和 [/robots.txt] 的访问日志。
# 并且即使它们不存在,也不写入错误日志。
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
# 将 [404] 错误交给 [/index.php] 处理,表示由 Laravel 渲染美观的错误页面。
error_page 404 /index.php;
# URI 符合正则表达式 [\.php$] 的请求将进入此段配置
location ~ \.php$ {
# 配置 FastCGI 服务地址,可以为 IP:端口,也可以为 Unix socket。
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /$document_root$fastcgi_script_name;
include fastcgi_params;
}
# 通俗地说,以上配置将所有 URI 以 .php 结尾的请求,全部交给 PHP-FPM 处理。
# 除符合正则表达式 [/\.(?!well-known).*] 之外的 URI,全部拒绝访问
# 也就是说,拒绝公开以 [.] 开头的目录,[.well-known] 除外
location ~ /\.(?!well-known).* {
deny all;
}
}
- 我在/home/app/hooks/下面写了一个脚本webhook.php,只要通过上述nginx代理可以成功解析,那么第一步就完成
<?php
echo '测试钩子接口是否调通';
- 总之一句话:首先你要编写一个接口文件,先不要管里面的代码是什么,只要可以调通就好!
4. gitlab添加钩子
- 每个项目都要配一个webhooks,因为每个项目可能控制的逻辑不一样以及分支代码不一样,所以为了后续可控,就需要每个仓库都要配置webhooks
- 配置页面如下
5. 编写钩子脚本业务代码
hook.php(主要是git push 触发后进行操作)
<?php
error_reporting(E_ALL);
// 根据token获取项目信息
function getProjectInfoByToken($token, $project_map)
{
$return = [];
foreach ($project_map as $map) {
if ($map['access_token'] == $token) {
$return = $map;
break;
}
}
return $return;
}
include_once './config.php';
// 这里填你的gitlab服务器ip
$valid_ip = array('192.168.1.xxx','192.168.1.xxx');
// 这是gitlab服务器上配置的access_token
$client_token = $_SERVER['HTTP_X_GITLAB_TOKEN'];
$client_ip = $_SERVER['REMOTE_ADDR'];
// 按照日期生成日志文件
$file_name = date('Y-m-d').'_'.'webhook.log';
$data = ['time' => date('Y-m-d H:i:s'), 'client_ip' => $client_ip];
$data = array_merge($data, $_POST, $_GET, $_SERVER);
$project = getProjectInfoByToken($client_token, $project_map);
if (empty($project)) {
$data['result'] = 'Token mismatch!';
$log_data = json_encode($data) . PHP_EOL . PHP_EOL;
var_dump(file_put_contents($file_name, $log_data, FILE_APPEND));
die('Token mismatch!');
}
if (!in_array($client_ip, $valid_ip)) {
$data['result'] = 'Ip mismatch!';
$log_data = json_encode($data) . PHP_EOL . PHP_EOL;
var_dump(file_put_contents($file_name, $log_data, FILE_APPEND));
die('Ip mismatch!');
}
$root = $project['root'];
$command = "cd " . $root . "; git pull origin develop 2>&1"; # 我更新的是develop分支代码
$data['command'] = $command;
// 执行shell命令,需要服务器启用exec函数,默认是关闭的
exec($command, $output);
// var_dump($output); //这样可以用浏览器调试输出
$data['result'] = $output;
$log_data = json_encode($data) . PHP_EOL . PHP_EOL;
var_dump(file_put_contents($file_name, $log_data, FILE_APPEND));
config.php(此文件是用来控制不同仓库的配置项,这样只需要一个hook.php脚本,就可以管理起来多个仓库,切记,每个仓库的秘钥不一样,否则如果一样,那么只会更新先读取到的第一个正确秘钥仓库)
<?php
return $project_map = [
'dev' => [
'name' => 'dev', # 别名
'access_token' => 'xxx-dev', # 配置钩子时需要的一个秘钥,当然也可以不设置
'root' => '/home/app/dev' # 仓库所在路径
],
'test' => [
'name' => 'test',
'access_token' => 'xxx-test',
'root' => '/home/app/test'
],
];
5. gitlab上面完善钩子信息
- 再次测试,是否可以走通(接下来会遇到一些列坑,现在给予相应的解决方法)
坑系列
- 不允许本地发起请求
Url is blocked: Requests to localhost are not allowed
解决方法
- .git无权限
error: cannot open .git/FETCH_HEAD: Permission denied
问题原因
由于脚本是PHP,在执行时是通过php-fpm的,而git的用户是root,所以要查看php-fpm的用户是谁。
找到php-fpm.conf文件或者相应的配置文件
解决方法
# 更改.git用户和用户组为php-fpm即可
chown -R nginx:nginx .git
# 这里要说一下:.git是要更新仓库所在的位置,也就是每一个仓库都需要执行这个操作
- 没有权限写入日志
# 以下只是没有权限错误的一种表现而已
error: unable to create file poetchao.txt (Permission denied)"
解决方法
chmod -R 777 仓库所在路径
- git pull 无权限
可能会出现下列问题:
Host key verification failed
fatal: Could not read from remote repository
Please make sure you have the correct access rights
and the repository exists
解决方法
- 清空/root/.ssh/known_hosts文件内容,然后进入到仓库,进行git pull 按照提示输入yes即可,此问题便解决!
出现下面这个问题:
"Permission denied, please try again.",
"Permission denied, please try again.",
"Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
"fatal: Could not read from remote repository.",
"Please make sure you have the correct access rights",
"and the repository exists."
问题原因
gitlab用户是root,但是执行php-fpm的用户是nginx,没有权限拉取
解决方法
- 一定要晓得php-fpm的用户是谁,因为钩子文件是PHP文件,git执行钩子文件中的函数时(git pull)
- 知道哪个用户去Git pull 之后,就要将这个用户下面生成的id_rsa.pub加入到gitlab的ssh-key列表中,然后就可以了
# 进入nginx(也就是php-fpm用户)家目录
cd /home/nginx/.ssh
# 生成ssh-key 一路回车
ssh-keygen -t rsa -f nginx -C 'nginx key'
# 执行上述命令生成两个文件,然后id_rsa id_rsa.pub,将id_rsa.pub内容添加到gitlab中的ssh-key处
至此,配置完成,如有疑惑,请留言,我将耐心解决!谢谢!