使用git的post-receive实现自动部署

栏目: 编程工具 · 发布时间: 5年前

内容简介:这事断断续续折腾我大概两周时间,这就把我经历的事分享给大家。为了实现在本地提交这个blog项目能不用手动到线上更新而努力着,刚开始在找解决办法时以为就那么简单,结果却折腾在docker、linux权限和如何写shell的几个关键知识里面。这里先简单介绍一下部署流程:

这事断断续续折腾我大概两周时间,这就把我经历的事分享给大家。

为了实现在本地提交这个blog项目能不用手动到线上更新而努力着,刚开始在找解决办法时以为就那么简单,结果却折腾在 dockerlinux 权限和如何写 shell 的几个关键知识里面。

流程

这里先简单介绍一下部署流程:

本地--[推送代码]-->git服务器--[触发]-->`post-receive`钩子--[拉取代码]-->部署目录

目前情况

以下是我目前的情况:

  • git服务和网站服务在同一个服务器上
  • 项目不存在构建,只把生成的内容放到固定分支
  • git服务用的是gogs
  • 用ssh方式拉取代码

处理办法

好了,具体怎么做?

post-receive

然后把下面代码添加进去:

#!/bin/bash

while read oldrev newrev refname
do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    if [ "gh-pages" == "$branch" ]; then
        # 在这添加你需要做的部署行为
    fi
done

接下来得说说关键部分的部署代码,根据我目前的情况,在部署代码之前需要做两件事情:

移除 GIT_DIR 环境变量

这里由于 GIT_DIR 默认为’.’,会导致访问地址不对并给出下面提示:

“fatal: Not a git repository: ‘.’”

处理办法:

unset GIT_DIR

生成密钥

为满足使用ssh方式拉取代码就会需要密钥,我gogs是跑在docker容器下,第一步先进入容器然后生成密钥:

ssh-keygen -t rsa -C "your name or email"

如何生成密钥这里就不详细说明,各位到网上自查攻略吧!

再来到gogs的[仓库设置]->[管理部署密钥]->[添加部署密钥]把公钥添加进去就能用了。

自定义ssh请求

为满足ssh指定加载特定密钥,需要在git执行前自定义ssh的操作:

GIT_SSH_COMMAND="ssh -i /git/.ssh/id_rsa" git fetch

GIT_SSH_COMMAND 只适用于 git version 大于 2.6 的版本

执行后会出现一堆提示而且不会执行git的具体操作:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
50:e6:cb:58:bc:b7:a3:f6:e8:8f:46:a7:c1:5f:c2:df.
Please contact your system administrator.
Add correct host key in /git/.ssh/known_hosts to get rid of this message.
Offending key in /git/.ssh/known_hosts:7
RSA host key for 192.168.0.4 has changed and you have requested strict checking.
Host key verification failed.

发送ssh请求会询问是否把相关信息记录至 known_hosts ,但是由于是脚本处理所以并没得到处理,最后会给出上面的提示。

解决办法有三种:

  1. 删除提示信息中,对应的行数,例如上例,需要删除/git/.ssh/known_hosts文件的第7行。
  2. 删除整份/git/.ssh/known_hosts文件。

上面两种并不能从根本解决问题,这里推荐在ssh命令后添加下面两个参数的第三种解决办法:

-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /git/.ssh/id_rsa" git fetch

写成这样就能带上给定的ssh密钥,到这里基本把需要解决的问题都解决了,下面给上完整代码:

#!/bin/bash

while read oldrev newrev refname
do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    if [ "gh-pages" == "$branch" ]; then

        printf "branch:$branch\n"

        PROJECT_ROOT=/www
        PROJECT_PATH="$PROJECT_ROOT/[目录地址]"
        REPO_PATH="[git地址]"
        REPO_BRANCH="$branch"

        # GIT_DIR默认为'.',会导致访问地址不对,故需要移除GIT_DIR环境变量
        # > https://alfred-long.iteye.com/blog/1836347
        unset GIT_DIR

        # `-o StrictHostKeyChecking=no` 不检查公钥
        # `-o UserKnownHostsFile=/dev/null` 不更新known_hosts
        # `-i /git/.ssh/uxfeel` 指定密钥
        # > https://www.cnblogs.com/zhengah/p/4959682.html
        GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /git/.ssh/uxfeel"
        export GIT_SSH_COMMAND

        if [ ! -d "$PROJECT_PATH" ]; then
          printf "git clone -b$REPO_BRANCH$REPO_PATH\n"
          cd "$PROJECT_ROOT"
          git clone -b "$REPO_BRANCH" "$REPO_PATH"
          printf "git clone finish.\n\n"
        else
          cd "$PROJECT_PATH"
          printf "git fetch \n"
          git fetch
          printf "git fetch finish.\n\n"

          printf "git pull \n"
          git pull
          printf "git pull finish."
        fi
    fi
done

这里说几点需要注意的:

  • 外部部署环境的目录权限尽量和容器里面生成目录的权限保持一致(能解决大部分的权限问题)
  • 搞清楚shell当前的权限所属再写shell(少走弯路,特别是你不太清醒的时候)
  • 应用只全局的变量一定要 export , export , export (重要的事情说三次,这个害我花了不少时间)

如果你的环境没那么复杂是真的不用考虑那么多,自己撸起可能会比我少走很多弯路,希望大家处理权限的时候记住:linux权限规则还是linux的权限规则,不要给docker给迷惑了!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

万万没想到

万万没想到

万维钢(同人于野) / 电子工业出版社 / 2014-10-1 / 39.80元

本书精选了万维钢老师的文章和书评,以“用理工科思维理解世界”为导向。作者常用有趣的实验、数据来解读感性的事物,其理工科思维涉及行为经济学、认知心理学、社会学、统计学、物理等许多学科,以前沿的科学视角解读生活,为人们提供了认知的新方法。读完本书相当于精读了十几本经过筛选 、再创作及通俗化处理的巨著,不仅有趣还十分有营养。一起来看看 《万万没想到》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具