本文主要介绍如何用git hooks
来进行自动化部署发布我们的代码,省去了我们发布前一系列不必要的打包发布等繁琐步骤。
背景
用git
管理代码时,每次发布时,我们都需要经过以下步骤:
- 将本地代码
push
至远程仓库; - 然后再
ssh
到服务器上进行git pull
操作; - 对代码进行编译打包压缩发布等吧啦吧啦各种无趣的操作;
这很是繁琐,本着程序猿(媛)能躺着就不坐着的基本素养,我们是不是能够自动去监测我们的远程仓库,当我们每次push
之后,它就自动去实现代码的更新编译部署等一系列功能呢?答案是,当然可以。
下面就开始漫漫踩坑路。
自动部署理论
首页,我们要明确项目代码的分布情况:开发者电脑的本地仓库,git服务器上的远程仓库,web服务器上的本地仓库(我们浏览访问的就是这里的代码)。
所谓自动部署,就是当我们将代码从本地仓库push到远程仓库时,自动把代码部署到web服务器上的本地仓库,实现开发者电脑的本地仓库和web服务器上的本地仓库代码同步。
git hooks
git有一个神器:git hooks,没了解过的话可以去官网了解下。
它的功能是能在特定的重要动作发生时触发自定义脚本。 它有两组这样的钩子:客户端的和服务器端的。 客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。 你可以随心所欲地运用这些钩子。
这里我们主要用到服务端的钩子:post-receive
。
环境搭建
本例服务器环境:
主机:111.111.111.111
用户:root
约定(可自定义):
裸仓库建在/home/workspace
下
web本地仓库建在/home/www
下
所属用户:git
Git服务器搭建
1.连接至服务器
ssh连接至服务器
1 |
ssh root@111.111.111.111 |
2.创建git用户
我们创建一个git
用户,专门用来运行git
服务:
1 2 |
sudo adduser git 创建用户 sudo passwd git 设置密码 |
3.创建裸仓库
我们在/home/workspace
文件夹下创建Git裸仓库:
1 2 3 |
mkdir /home/workspace cd /home/workspace git init --bare layercake.git |
配置Git Hooks
进入/home/workspace/layercake.git
文件夹,使用vi post-receive
创建一个脚本。
1 2 |
cd /home/workspace/layercake.git/hooks vi post-receive |
当我们本地git push
之后就会触发服务器上的post-receive
脚本。
post-receive
内容如下:
1 2 3 4 5 |
unset GIT_DIR cd /home/www/layercake git pull |
这是一个简单的脚本,文章结尾有更复杂的post-receive
配置,可以根据不同分支进行不同操作。
再配置post-receive
权限:
1 |
chmod +x post-receive |
创建代码仓库
然后我们在/home/www
下创建一个代码仓库,关联先前创建的layercake
仓库:
1 2 3 |
mkdir /home/www cd /home/www git clone /home/workspace/layercake.git |
配置公钥
如不配置公钥,每次本地push
时都会要求输入服务器密码,不胜其烦,故我们配置下公钥来跳过这一步骤。
将本机的公钥加入至/home/git/.ssh/authorized_keys
中,authorized_keys
文件里包含所有该项目的开发者们的ssh公钥。
如果服务器上没有该文件则创建它:
1 2 3 4 5 6 |
mkdir /home/git cd /home/git mkdir .ssh chmod 755 .ssh touch .ssh/authorized_keys chmod 644 .ssh/authorized_keys |
如本地没有创建过密钥,则执行ssh-keygen -t rsa -C xx
来创建自己本地的密钥,xx
为自己的邮箱,然后按提示操作即可。
此时本地会生成.ssh
文件夹,打开里面的id_rsa.pub
文件,复制内容粘贴至上面说的authorized_keys
文件中就即可。
然后设置下仓库所属用户(git):
1 2 3 |
sudo chown -R git:git /home/workspace/layercake.git sudo chown -R git:git /home/www/layercake sudo chown -R git:git /home/git |
本地克隆仓库
在本地电脑上,克隆服务器上的git仓库:
1 |
git clone git@111.111.111.111:/home/workspace/layercake.git |
按照提示输入服务器密码即可。
到此,全部配置已完成,以后每次本地仓库push
至远程仓库时,都会触发post-receive
脚本,从而更新/home/www/layercake
仓库代码。
完整版post-receive
脚本配置
功能:
1.根据不同分支进行不同操作:
我们可以定义不同分支,当该分支push后触发对应操作,如dev_debug
分支更新时触发测试库代码更新。
2.跨服务器操作:
当我们的web服务器代码和服务器上的本地代码位于不同服务器时,通过rsync
命令进行文件或目录的复制。
每次rsync
命令复制时,都需要输入接收服务器的密码,这不是程序猿(媛)的风格,所以我们也采用公钥配置方式来免去输入密码这一步。
假如web服务器(F2):
主机:222.222.222.222
用户:root
本例中远程仓库(F1):
主机:111.111.111.111
用户:git
F1服务器操作:
ssh
连接至F1,创建密钥:
1 2 3 |
ssh git@111.111.111.111 # 连接至服务器,按提示输入密码ssh-keygen -t rsa # 创建密钥(如F1服务器还未创建密钥),一路回车,无须设置密码 |
在.ssh
目录下会生成id_rsa
(私钥)和 id_rsa.pub
(公钥)两个文件,复制id_rsa.pub
中的内容。
F2服务器操作:
连接上F2服务器,将F1公钥添加至/root/.ssh/authorized_keys
中即可。
1 2 3 4 5 |
ssh root@222.222.222.222 # 连接至服务器,按提示输入密码 vi /root/.ssh/authorized_keys // 添加F1的公钥,保存退出chmod 600 /root/.ssh/authorized_keys # 设置文件权限600 |
有时候连接服务器会出现以下错误:
1 |
Are you sure you want to continue connecting (yes/no)? |
我们是脚本运行,所以不好去输入yes
,解决方法有两种:
1.在F1的post-receive
脚本中使用ssh -o
的参数进行设置:
1 |
ssh -o StrictHostKeyChecking=no root@222.222.222 |
2.修改F2服务器中/etc/ssh/ssh_config
:
将其中的# StrictHostKeyChecking ask
改成StrictHostKeyChecking no
。
本例采用第一种方法。
以下是本例中完整的post-receive
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# web服务器本地仓库目录 DEPLOY_PATH="/home/www/layercake"# 测试库分支、测试服务器 dev_debug="dev_debug" debug_user="root" debug_host="222.222.222.222" debug_path="${debug_user}@${debug_host}:/home/www"# 灰度分支、灰度服务器 dev_test="dev_test" test_user="root" test_host="222.222.222.222" test_path="${test_user}@${test_host}:/home/www"# 正式库分支、正式服务器 dev_prod="master" prod_user="root" prod_host="222.222.222.222" prod_path="${prod_user}@${prod_host}:/home/www"###### 用户配置区 结束 ######path="none"# 去掉Git默认的环境变量 unset GIT_DIRwhile read oldrev newrev refname do# 当前分支branch=$(git rev-parse --symbolic --abbrev-ref $refname)echo "======= start ======="echo "Target branch: $branch"# 指定到项目文件夹cd $DEPLOY_PATH# 创建分支(已存在会提示已存在,继续往下执行)git branch $branch# 指定到该分支git checkout $branch# 拉取代码git pull origin $branch:$branch# 根据分支判断上传环境case $branch in$dev_debug)envName="测试库"path=${debug_path}user=${debug_user}host=${debug_host};;$dev_test)envName="灰度"path=${test_path}user=${test_user}host=${test_host};;$dev_prod)envName="正式库"path=${prod_path}user=${prod_user}host=${prod_host};;*)echo "fail!";;esac# 上传至测试环境、灰度、正式环境if [ $path != "none" ]thenssh -o StrictHostKeyChecking=no ${user}@${host}# -r 拷贝文件夹# -v 显示详情rsync -r -v $DEPLOY_PATH $pathecho "publish to $envName..."fiecho "======= end =======" done |
转载待测试,如果有问题请留言讨论,不喜勿喷!