头图

最近在使用阿里云 Code 的 git仓库,每次 push 了代码之后还要去手动 pull,很麻烦就准备配置下webhook。
我们的开发语言是 PHP,所以就使用PHP 的 shell_exec 来执行 shell 脚本,下面就简单说下
配置流程。

注意:PHP 开放 shell_exec 等危险性内置函数是很危险的,万一,是吧~

修改 www 用户执行权限

因为 nginx + php 都是 www 用户来执行的,而且 www 一般都配置为不允许 ssh 登录的。那么就需要更改下 www 的执行权限了,这个配置是在 /etc/sudoers 配置文件中设置,找到 root ALL=(ALL) ALL,在这个下面添加如下配置,对于这个权限的设置如果不明白就要咨询下运维的童鞋了,我这里只是简单的演示配置:

root    ALL=(ALL)     ALL
www     ALL=(ALL)     NOPASSWD:/bin/chown,/bin/chmod,/usr/bin/git

解释下这里的 ALL 都是什么意思:

  1. 第一个ALL表示所有计算机;
  2. 第二个ALL表示所有用户;
  3. 第三个ALL表示所有命令;

说下我这条配置的意思,授权www用户不用密码在所有计算机上以root身份运行chown,chmod,git命令

编写 webhook.php

webhook 这个可以根据使用的不同的 git 仓库(Gitee、Github、coding、阿里云code...)配置,大致内容就是校验IP、校验签名、校验hook事件类型等,我这里只配置了推送事件才会触发 hook,所以就没有对事件进行校验

<?php
// 开启日志记录
$fs = fopen(__DIR__.'/hook.log', 'a');
fwrite($fs, '================ Update Start ==============='.PHP_EOL.PHP_EOL);
fwrite($fs, 'Request on ['.date("Y-m-d H:i:s").']'.PHP_EOL);
// 获取阿里云 code 的IP
$allow_ip = array('121.43.182.162');
$client_ip = $_SERVER['REMOTE_ADDR'];
if (!in_array($client_ip, $allow_ip)) {
    fwrite($fs, "error 403 Request ip [{$client_ip}]".PHP_EOL);
    exit(0);
}
// 判断推送事件
$event = $_SERVER['HTTP_X_GITLAB_EVENT'];
if (strcmp($event, 'Push Hook') !== 0) {
    fwrite($fs, "error 403 Request event [{$event}]".PHP_EOL);
    exit(0);
}

// 判断自定义的签名,这个是在填写 webhook 地址的时候自己填写的,比如:http://www.xxx.com/webhooks.php?sign=xxxxxx
$sign = 'xxxxxx';
$get_sign = isset($_GET['sign']) ? $_GET['sign'] : '0';
if (strcmp($sign, $get_sign) !== 0) {
    fwrite($fs, "error 403 Request sign [{$get_sign}]".PHP_EOL);
    exit(0);
}
// 获取发送的数据,是 json 格式的
$json = file_get_contents('php://input');
$data = json_decode($json, true);
// 这里是记录推送数据,有需要就记录
fwrite($fs,PHP_EOL. '================ 发送的数据 ==============='.PHP_EOL.PHP_EOL);
fwrite($fs, 'Data: '.$json.PHP_EOL);
fwrite($fs,PHP_EOL. '================ 发送的 header 头 ==============='.PHP_EOL.PHP_EOL);
fwrite($fs, 'header: '.json_encode($_SERVER, JSON_UNESCAPED_UNICODE).PHP_EOL);

// 校验是什么分支推送,可根据自己的需要选择是 master、develop、release 分支
$ref = 'refs/heads/master';
$push_ref = $data['ref'];
$object_kind = $data['object_kind'];

if (strcmp($ref, $push_ref) !== 0 && strcmp('push', $object_kind) !== 0) {
    fwrite($fs, "error 403 Request heads [{$push_ref}] object_kind [{$object_kind}]".PHP_EOL);
    exit(0);
}

$output = shell_exec('/home/www/www.xxxx.com/webhook.sh');
fwrite($fs, 'Info:'. var_export($output,true).PHP_EOL);
fwrite($fs,PHP_EOL. '================ Update End ==============='.PHP_EOL.PHP_EOL);
$fs and fclose($fs);
echo "success";

编写 webhook.sh

#!/bin/bash
 
WEB_PATH='/home/www/project'
WEB_USER='www'
WEB_USERGROUP='www'
 
echo "Start ..."
cd $WEB_PATH
echo "pulling source code..."

sudo git fetch --all
sudo git reset --hard origin/master
sudo git clean -f
sudo git pull

echo "changing permissions..."
sudo chown -R $WEB_USER:$WEB_USERGROUP $WEB_PATH
sudo chmod -R 0755 $WEB_PATH
echo "Finished."

/etc/sudoers 中配置了 www,所以这里使用 sudo

上面设置完毕就可以去测试下了,我测试的是成功的,如果你没有成功就使用定时器的方式吧

其他方式

使用 crontab 定时器定时拉取

/etc/sudoers 文件介绍参考:《sudo配置文件/etc/sudoers详解及实战用法》《/etc/sudoers配置文件详解(转)》


其名
10 声望2 粉丝

Hello World!