用git hooks进行自动部署,从此不需要登录服务器

昨天刚折腾好博客,喜欢折腾的我又发现了一个问题——每次我在本地hexo deploy完都需要登录服务器去:

1
2
git pull
sudo nginx -s reload

作为一个程序猿,怎么能忍受这么不geek这么不技术的事情发生!

于是,我就想到了,能不能我在本地git push之后自动在服务器上git pull然后自动重启nginx呢?

于是Google了一下,发现果然前辈们的智慧是无穷尽的,早就有人提供了解决方案,我就来整理 & 搬运一下。

有一个东西叫做git hook,这个东西是干嘛的呢?简单来说,就是在git的执行流程中设置了断点,执行到某个流程的时候先去执行一下我们设置好的脚本,再接着执行。

艾玛,这可是个好东西,就决定用这玩意了。

生成 ssh 密钥

首先呢,我们得先配置一下我们的服务器,让我们ssh可以不用输密码就能登录:

1
2
cd ~/.ssh
ssh-keygen -t rsa -C "你的邮箱或者任何字符串"

这里我们一直回车到结束就可以了,默认名字是~/.ssh/id_rsa~/.ssh/id_rsa.pub,其中带有pub的是公钥,是要传给服务器的,私钥一定一定一定要保存好,不能泄漏。

然后我们用ssh去登陆服务器,通过用户名和密码登陆

1
2
# 在服务器环境下
vim ~/.ssh/authorized_keys

然后在本机上执行

1
2
# 在本机环境下
pbcopy < ~/.ssh/id_rsa.pub

把我们的公钥复制到剪贴板,再复制到服务器中的~/.ssh/authorized_keys中,然后退出服务器的登陆,回到本机环境下:

1
2
# 在本机环境下
vim ~/.ssh/config

在里面加入以下内容:

1
2
3
4
5
6
Host HOST_ALIAS                       # 用于 SSH 连接的别名,最好与 HostName 保持一致,都用ip或者都用域名
HostName SERVER_DOMAIN # 服务器的域名或 IP 地址
Port SERVER_PORT # 服务器的端口号,默认为 22,可选
User SERVER_USER # 服务器的用户名
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa # 本机上存放的私钥路径

大功告成!

配置服务器上的 git 仓库

这里需要先介绍一下 git init —bare

git init —bare

git init 不一样的是,git init --bare并不存储实际代码,仓库文件夹不会看到任何项目代码,反而生成了一些 .git之外的文件夹,其中 hooks文件夹就是存放git命令操作后需要执行的脚本。
需要新建两个文件夹,一个执行git init --bare作为远端仓库,一个执行git init作为服务器项目目录。
本地开发目录和服务器项目目录的remote都要指向 服务器的远端仓库。

在服务器上创建一个裸仓库

首先要在服务器上建立一个裸仓库,假设我们用于存放裸仓库的文件夹是/home/user/repos/,进入到该文件夹,然后使用git init --bare test.git创建裸仓库,这样我们就有了一个叫test.git的裸仓库啦。

在服务器上创建一个普通Git仓库

接下来就是在服务器上建立一个普通Git仓库,用于存放网站的源代码。

1
2
3
4
mkdir /home/user/www
cd /home/user/www
git init
git clone ~/repos/test.git
配置Git Hook

进入到~/repos/test.git/hooks文件夹,使用vi post-receive创建一个脚本,当你在本地仓库执行git push后就会触发post-receive关于Git Hok)。
post-receive的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh

unset GIT_DIR

NowPath=`pwd`
DeployPath="../../www"

cd $DeployPath
git add . -A && git stash
git pull origin master
echo "your root password" | sudo -S nginx -s reload
cd $NowPath
echo "deploy done"
exit 0

默认的情况下,脚本是无法执行的,所以我们需要为这个脚本添加可执行权限
chmod +x post-receive

本地仓库配置

这里的本地仓库就是你本机的仓库,不再是服务器上的了。我们要在原有的Git项目中加入一条新的remote源,以后往这个源推送代码就会自动部署了。

1
2
git remote add prod user@ip_address:repos/test.git
git push prod master

如果是用hexo的自动部署的话,需要在_config.yml文件里面的deploy中的repo改成如下:

1
2
3
4
5
deploy:
type: git
repo:
github: <repository url>
prod: user@ip_address:repos/test.git

然后我在本地又写了一个deploy.sh的脚本,来一键部署:

1
2
3
hexo clean
hexo g
hexo d

别忘了

1
chmod +x deploy.sh

然后部署的时候只要

1
./deploy.sh

就可以了!

Done!

程序猿就是这么鸡汁!