记录一下使用Git钩子来实现网站的自动部署
概念
- 本地仓库:平时开发所在的环境,可以简单的理解为自己的电脑,记为L1
- 远程git服务器:
git
服务所在的服务器,比如我们自己内部搭建的gitlab
服务运行在31服务器上,记为G1 - 远程仓库: 运行仓库代码运行所在的服务器,比如我们的
webserver
运行的服务器,记为R1
在这里,我们的G1和R1恰好是同一台机器
准备
假设G1上已经有存在的仓库webserver
,并且在L1和R1上都已经有通过git clone
命令下载过来的版本一致的代码。并且R1上运行'webserver的用户为
user1`
ssh免密登录
首先要实现运行git
服务的用户(用户git)和user1
的ssh
免密登录。即git
可以通过
ssh user1@xxx.xxx.xxx.xxx
直接登录user1
在git
用户下,运行命令
ssh-keygen
会在git
的 home
目录下生成私钥和公钥文件:
~/.ssh/id_rsa #私钥
~/.ssh/id_rsa.pub #公钥
如果home目录下已经存在密钥文件,则不需要重新生成。否则以前生成的密钥会失效!
将git
用户的公钥添加到user1
的~/.ssh/authorized_keys
中,即
cat ~/.ssh/id_rsa.pub >> /home/user1/.ssh/authorized_keys #权限问题,这个命令不会成功,自己实现相同的结果即可
然后在user1
下修改authorized_keys
的权限:
chmod 600 ~/.ssh/authorized_keys
再回到git
用户下,执行:
ssh user1@xxx.xxx.xxx.xxx
不用输入密码,即可直接登录user1
用户
拉取更新脚本
在user1
用户下,新建一个脚本,实现从仓库拉取更新的功能,示例如下:
#!/bin/sh
DeployPath="/mnt/analysis/tests/test_uesr1/tmp/webserver" #远程仓库路径
cd $DeployPath
IS_BARE=$(git rev-parse --is-bare-repository)
if [ -z "$IS_BARE" ]; then
echo >&2 "fatal: post-receive: IS_NOT_BARE"
exit 1
fi
unset GIT_DIR
echo "=========================="
echo "deploying the webserver"
git fetch --all #使用fetch,不会自动merge
git reset --hard origin/master #强制和远程仓库保持一致
time=`date`
echo "webserver fetch at time: $time."
echo "=========================="
可以将此脚本放在'home
目录下,命名为git_fetch.sh
钩子的实现
git
服务在服务器上会有相应的目录,在该目录下会有所有用户的所有仓库信息。因为我们要实现的是服务端钩子,所以需要在git
服务的服务器上设置。
在我们的G1上运行的是gitlab
服务,路径为:
/var/opt/gitlab
注意:git
用户的home
目录也在该路径下
在该路径下的git-data/repositories
目录保存的就是仓库信息。进入我们需要设置钩子的仓库,比如:
/var/opt/gitlab/git-data/repositories/user1/webserver.git
在这个目录下,有一个hooks
目录,这是一个软连接,里面是全局钩子。这里的钩子修改,所有的仓库都会执行。
因为我们只想设置单独的仓库,所以我们需要在当前仓库新建一个custom_hooks
的目录,这个名称是写死的,不能用其他名称。
在custom_hooks
下新建post-receive
文件,名称同样是定死的。这个名称的钩子代表push
之后执行的动作:
mkdir custom_hooks #/var/opt/gitlab/git-data/repositories/user1/webserver.git/custom_hooks
cd custom_hooks
vim post-receive # 注意是横扛,不是下划线
在post-receive
里写以下命令:
#!/bin/sh
ssh user1@xxx.xxx.xxx.xxx "sh ~/git_fetch.sh" #即登录user1,然后user1执行拉取更新的脚本
以上新建文件夹和文件的步骤如果是用root
或者其他非git用户操作的,操作完后需要把所有者改成git
:
chown -R git:git custom_hooks
chmod -R 777 custom_hokks # 755应该也可以
到此钩子的设置就完成了。接下来在本地L1修改完代码push
到远程仓库后,R1上的代码也会自动从远程仓库拉取更新。
总结
工作流程其实很简单,主要是要分清各个角色执行的功能。
- L1修改代码,然后push给远程仓库,即G1
- G1上的仓库有
post-receive
钩子,但是执行用户是git
。git
用户无权限对user1
的仓库进行操作,所以通过ssh
的方式登录到user1
执行拉取更新的操作
本文首发于公众号:柠檬培养师(ID: yantinger90),欢迎关注!