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

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

内容简介:这事断断续续折腾我大概两周时间,这就把我经历的事分享给大家。为了实现在本地提交这个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给迷惑了!


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

查看所有标签

猜你喜欢:

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

Game Programming Patterns

Game Programming Patterns

Robert Nystrom / Genever Benning / 2014-11-2 / USD 39.95

The biggest challenge facing many game programmers is completing their game. Most game projects fizzle out, overwhelmed by the complexity of their own code. Game Programming Patterns tackles that exac......一起来看看 《Game Programming Patterns》 这本书的介绍吧!

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

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具