Golang 项目部署实战

2023-11-17

一直认为不懂部署的开发工程师不是好的开发工程师,以下以一些实例讲解自己在项目中的 Golang 后端部署的情况。

一般部署脚本应该具有构建、启动、停止、回滚已经查看记录日志等功能,以下分别将这些功能以单个脚本的形式给出,当然也可以写成Makefile 的形式。

单个部署脚本的形式,在一个目录下建立如下文件:

bin # 目录,用于存放每次 build 之后存放的二进制文件
app.log # 用来记录的日志文件
log.sh # 实时查看日志
build.sh # 构建
run.sh # 启动某一次编译版本
start.sh # 启动最新版本,并且备份之前前一次运行的版本
shutdown.sh # 停止
rollback.sh # 回滚到上一版本


本例中的 GOPATH=”/go”

log.sh 具体内容:

tail -f -n 200 app.log # 实时查看最后 200 条日志的情况

build.sh 具体内容:

#!/bin/bash

# 项目地址,/go 在 GOPATH 里面
baseProjectDir="/go/src/monitor"

# targetDir 编译后的二进制文件目录
targetDir="bin"

# branch 编译的分支
branch="master"

pwd=`pwd`
# targetFile 编译后的输出文件名称
targetFile=`basename $pwd`

# buildPkg 编译的包名,main.go 所在的包
buildPkg="monitor"

# buildResult 编译结果
buildResult=""

if [ -n "$1" ]; then
  branch="$1"
  echo "Switch branch to ${branch}"
else
  echo "Building Branch: ${branch}"
fi

gitPull() {
  pushd .

  cd "$baseProjectDir"
  git checkout "$branch"
  git pull

  popd
}

goBuild() {
    buildResult=`go build -o "${targetDir}/${targetFile}" "$buildPkg" 2>&1`

    if [ -z "$buildResult" ]; then
      buildResult="success"
    fi
}

gitPull
goBuild

if [ "$buildResult" = "success" ]; then
  cp ${targetDir}/${targetFile} ${targetFile}-new
  chmod +x ${targetFile}-new
else
  echo "build error $buildResult"
  exit
fi

echo "All Complete"


run.sh 具体内容:

#!/bin/bash

# 以后台方式启动程序,并且将日志记录到 app.log
nohup ./$1 >> app.log &


start.sh 具体内容:

#!/bin/bash

pwd=`pwd`
target=`basename $pwd`
# kill
pid=`ps -C ${target} -o pid=`
if [ -n "$pid" ]; then
  echo "Stopping old version, PID: ${pid}"
  if [ "$1" = "-f" ]; then
    # force shutdown
    echo "Force shutdown..."
    kill -9 $(ps -C ${target} -o pid=)
  else
    kill -s 2 $(ps -C ${target} -o pid=)
  fi
  # wait for program to stop
  pid=`ps -C ${target} -o pid=`
  while [ -n "$pid" ]; do
    sleep 1
  done
fi

# upgrade
if [ -f "${target}-new" ]; then
  echo "Upgrading..."
  if [ -f "${target}-backup" ]; then
    backupdt=`date +%Y%m%d-%H`
    mv "${target}-backup" "${target}-backup-${backupdt}"
  fi

  mv ${target} ${target}-backup
  mv ${target}-new ${target}

  echo "Upgrade Complete"
fi

# run
echo "Starting..."
./run.sh ${target}
echo "Done"


shutdown.sh 具体内容:

#!/bin/bash

pwd=`pwd`
target=`basename $pwd`

# kill
pid=`ps -C ${target} -o pid=`
if [ -n "$pid" ]; then

  echo "Stopping old version, PID: ${pid}"
  if [ "$1" = "-f" ]; then
    # force shutdown
    echo "Force shutdown..."
    kill -9 $(ps -C ${target} -o pid=)
  else
    kill -s 2 $(ps -C ${target} -o pid=)
  fi

  # wait for program to stop
  pid=`ps -C ${target} -o pid=`
  while [ -n "$pid" ]; do
    sleep 1
  done

fi

echo "Done"


需要注意的是 kill -s 2 发送的是 Interrupt 中断信号,在项目中要有监听该信号的处理程序,eg:

package main

import (
    "log"
    "os"
    "os/signal"

    "github.com/robfig/cron"
)

func main() {
    i := 0
    c := cron.New()
    spec := "*/3 * * * * ?"
    c.AddFunc(spec, func() {
        i++
        log.Println("cron running:", i)
    })
    c.Start()

    go signalListen()

    select {}
}

func signalListen() {
    c := make(chan os.Signal)
    // 监听 os.Interrupt 并且退出程序
    signal.Notify(c, os.Interrupt, os.Kill)
    for {
        <-c
        os.Exit(0)
    }
}


rollback.sh 具体内容:

#!/bin/bash

pwd=`pwd`
target=`basename $pwd`

# Kill running program
pid=`ps -C ${target} -o pid=`
if [ -n "$pid" ]; then

  echo "Stopping old version, PID: ${pid}"
  if [ "$1" = "-f" ]; then
    # force shutdown
    echo "Force shutdown..."
    kill $(ps -C ${target} -o pid=)
  else
    kill -s 2 $(ps -C ${target} -o pid=)
  fi

  # wait for program to stop
  pid=`ps -C ${target} -o pid=`
  while [ -n "$pid" ]; do
    sleep 1
  done
fi

# Rollback
if [ -f "${target}-backup" ]; then
  echo "Rolling back..."
  if [ -f "${target}" ]; then
    rm "${target}"
  fi
  mv ${target}-backup ${target}
  echo "Rollback Complete"
fi

# run
echo "Starting..."
./run.sh ${target}
echo "Done"


--------------------- 
作者:极客Geek 
来源:CSDN 
原文:https://blog.csdn.net/netdxy/article/details/79431415 
版权声明:本文为博主原创文章,转载请附上博文链接!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang 项目部署实战 的相关文章

  • go-zero使用Etcd进行服务注册代码分析

    代码分析 github com tal tech go zero v1 2 3 core discov publisher go package discov import github com tal tech go zero core
  • golang: Logrus实现日志打印

    Github https github com sirupsen logrus golang标准库的日志框架非常简单 仅仅提供了print panic和fatal三个函数 对于更精细的日志级别 日志文件分割以及日志分发等方面并没有提供支持
  • go Cobra命令行工具入门

    简介 Github https github com spf13 cobra Star 26 5K Cobra是一个用Go语言实现的命令行工具 并且现在正在被很多项目使用 例如 Kubernetes Hugo和Github CLI等 通过使
  • Go_关键字、编译、转义字符

    关键字 关键字是指被go语言赋予了特殊含义的单词 共25个 关键字不能用于自定义名字 只能在特定语法结构中使用 break default func interface select case defer go map struct cha
  • Jenkins系列:3、wsl/ubuntu安装Jenkins及Jenkins构建可交叉编译的go程序

    Jenkins系列 3 wsl ubuntu安装Jenkins及Jenkins构建可交叉编译的go程序 文章目录 Jenkins系列 3 wsl ubuntu安装Jenkins及Jenkins构建可交叉编译的go程序 1 前言 2 wsl
  • Go切片排序

    Go 语言标准库提供了sort包 用于对切片和用户定义的集合进行排序 具体示例如下 基本排序 package main import fmt sort func main float 从小到大排序 f float64 5 2 1 3 0 7
  • Golang连接Jenkins获取Job Build状态及相关信息

    文章目录 1 连接Jenkins 2 controller 3 module 4 router 5 效果展示 第三方包 gojenkins 方法文档 gojenkins docs 实现起来很简单 利用第三方库 连接jenkins 调用相关方
  • go 进阶 go-zero相关: 七. 拦截器与熔断拦截器

    目录 一 拦截器的基础使用 1 服务端拦截器 2 客户端拦截器 二 拦截器底层底层执行原理 三 go zero默认添加的拦截器 客户端 1 熔断器拦截器 BreakerInterceptor 服务端 一 拦截器的基础使用 在go zero
  • Go 语言注释教程

    注释是在执行时被忽略的文本 注释可用于解释代码 使其更易读 注释还可用于在测试替代代码时防止代码执行 Go支持单行或多行注释 Go单行注释 单行注释以两个正斜杠 开头 在 和行尾之间的任何文本都将被编译器忽略 不会被执行 示例 This i
  • Go 程序编译过程(基于 Go1.21)

    版本说明 Go 1 21 官方文档 Go 语言官方文档详细阐述了 Go 语言编译器的具体执行过程 Go1 21 版本可以看这个 https github com golang go tree release branch go1 21 sr
  • 掌握 Go 语言中的循环结构:从基础到高级

    一 if else 分支结构 1 if 条件判断基本写法 package main import fmt func main score 65 if score gt 90 fmt Println A else if score gt 75
  • 【go语言开发】编写单元测试

    本文主要介绍使用go语言编写单元测试用例 首先介绍如何编写单元测试 然后介绍基本命令的使用 最后给出demo示例 文章目录 前言 命令 示例 前言 在go语言中编写单元测试时 使用说明 测试文件命名 在 Go 语言中 测试文件的命名应与被测
  • go-zero开发入门-API网关开发示例

    开发一个 API 网关 代理 https blog csdn net Aquester article details 134856271 中的 RPC 服务 网关完整源代码 file main go package main import
  • go-zero开发入门之网关往rpc服务传递数据1

    go zero 的网关往 rpc 服务传递数据时 可以使用 headers 但需要注意前缀规则 否则会发现数据传递不过去 或者对方取不到数据 go zero 的网关对服务的调用使用了第三方库 grpcurl 入口函数为 InvokeRPC
  • GoLong的学习之路,进阶,微服务之序列化协议,Protocol Buffers V3

    这章是接上一章 使用 RPC包 序列化中没有详细去讲 因为这一块需要看的和学习的地方很多 并且这一块是RPC中可以说是最重要的一块 也是性能的重要影响因子 今天这篇主要会讲其使用方式 文章目录 Protocol Buffers V3 背景以
  • Go 语言中切片的使用和理解

    切片与数组类似 但更强大和灵活 与数组一样 切片也用于在单个变量中存储相同类型的多个值 然而 与数组不同的是 切片的长度可以根据需要增长和缩小 在 Go 中 有几种创建切片的方法 使用 datatype values 格式 从数组创建切片
  • [每周一更]-(第55期):Go的interface

    参考地址 https juejin cn post 6978322067775029261 https gobyexample com interfaces https go dev tour methods 9 介绍下Go的interfa
  • go cannot find package “github.com/gorilla/websocket“解读

    Go无法找到包 github com gorilla websocket 的解决方案 在Go开发过程中 我们经常会依赖第三方库来简化开发工作 而使用 go get 命令安装这些库时 有时候我们可能会遇到类似于以下错误的情况 plaintex
  • 【go语言】读取toml文件

    一 简介 TOML 全称为Tom s Obvious Minimal Language 是一种易读的配置文件格式 旨在成为一个极简的数据序列化语言 TOML的设计原则之一是保持简洁性 易读性 同时提供足够的灵活性以满足各种应用场景 TOML
  • 【go语言】AST抽象语法树详解&实践之扫描代码生成错误码文档

    背景 为了能识别出代码中抛出错误码的地址和具体的错误码值 再根据错误码文件获取到错误码的具体值和注释 方便后续的排错 这里使用AST进行语法分析获取到代码中的目标对象 一 编译过程 在开始解析代码之前先补充了解一下编译过程 编译过程是将高级

随机推荐

  • 用Python爬虫接私活,赚了32K!

    网络爬虫 很多人觉得这是技术控的专属 实际上爬虫是人人都能掌握的技能 爬虫到底能干什么 基本你所能看到的全部信息 它都能抓取 例如 收集并批量下载某音乐软件付费歌曲 某视频软件的付费视频 采集北京所有小区的信息及北京所有小区的所有历史成交记
  • centos7 lvm 创建脚本

    centos7 lvm 创建脚本 Centos7 lvm创建 适用场景只有一块新加的磁盘 且未分区 挂载目录为riva 可自定义 date 2023 bin bash 注意此处变量 Disk dev sd 不同的平台会有差异 比如腾讯云为
  • Attempted to load tokenizers/punkt/PY3/english.pickle

    分明已经把punkt放到服务器相应文件下 但是还是显示没成功 错误原因是解压得时候文件目录有两个punkt
  • VUE之自定义插件

    index js文件 import promptBox from prompt box vue 定义插件对象 const PromptBox vue的install方法 用于定义vue插件 PromptBox install functio
  • rocketMq介绍和安装

    rocketMq介绍和安装 Mq介绍 MQ MessageQueue 消息队列 队列 是一种FIFO 先进先出的数据结构 消息由生产者发送到MQ进行排队 然后按原来的顺序交由消息的消费者进行处理 QQ和微信就是典型的MQ MQ的作用 主要有
  • Vue项目中如何引入外部js文件,并使用其中定义的函数

    Vue项目中如何引入外部js文件 并使用其中定义的函数 一些常用的功能函数 我们希望将其封装起来放入一个外部JS文件中 好方便我们在需要的时候使用 vue可以使用import指令引入外部文件 但是作为新手 在使用过程中难免会导致很多错误 这
  • maven导入依赖失败问题——最系统、最彻底的解决方案

    目录 一 idea配置maven 1 配置maven版本及本地仓库 二 清理Local Repository的 lastUpdated文件 三 在idea中重新导入依赖 一 idea配置maven 1 配置maven版本及本地仓库 关于项目
  • 排序算法之堆排序(Heap Sort)——C语言实现

    堆排序 Heapsort 是指利用堆积树 堆 这种数据结构所设计的一种排序算法 它是选择排序的一种 算法分析 在学习堆排序之前我们要先了解堆这种数据结构 堆的定义如下 n个元素的序列 k1 k2 kn 当且满足以下关系时 称之为堆 若将此序
  • 短视频平台-小说推文(知乎)推广任务详情

    知乎会员 知乎日结内测中 可能暂只对部分优质会员开放 2023 03 29通知 知乎拉新项目 由于内部测试转化较低 暂时下线 原有关键词出单不受影响 1 关键词 1 1 选择会员文 在知乎 首页 或者 会员 里面选取 需要选取文章链接 点进
  • 二.centos7和主机实现xftp传文件,包含解决一些主机虚拟机互联的问题

    首先打开安装好的centos7 一 需要获取的信息 虚拟机 ifconfig 信息 主要是ensxx的信息 主机 ipconfig 信息 主要是vm8的信息 虚拟机点 编辑 虚拟网络编辑器 界面 查看虚拟机右下是否连接 点虚拟机右上角 看有
  • Nacos启动: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorExceptionTable nacos_config.config_inf

    把nacos 1 1 4 server下载到本地之后 然后直接在bin目录下启动startup cmd报错 本地Mysql版本 5 6 44 nacos server版本 1 1 4 我找了很多解决办法 更多的说的是nacos自带的mysq
  • vue 实时往数组里追加数据

    使用Vue set 以下来解读一下 Vue set this tableDatas this selected obj 1 this tableDatas是我们声明好的数组 以下是自定义数据 tableDatas id 1 caseName
  • Python之数据分析(三维立体图像、极坐标系、半对数坐标)

    文章目录 写在前面 一 三维立体图像 1 三维线框 2 三维曲面 3 三维散点 二 极坐标系 三 半对数坐标 写在前面 import numpy as np import matplotlib pylab as mp 因此文章中的np就代表
  • Linux学习大纲

  • 以太网设计FAQ:以太网MAC和PHY

    问 如何实现单片 以太网 微控制器 答 诀窍是将微控制器 以太网媒体接入控制器 MAC 和物理接口收发器 PHY 整合进同一芯片 这样能去掉许多外接元器件 这种方案可使MAC和PHY实现很好的匹配 同时还可减小引脚数 缩小芯片面积 单片以太
  • MySQL第一讲 一遍让你彻底掌握MVCC多版本并发控制机制原理

    Mysql在可重复读隔离级别下 同样的sql查询语句在一个事务里多次执行查询结果相同 就算其它事务对数据有修改也不会影响当前事务sql语句的查询结果 这个隔离性就是靠MVCC Multi Version Concurrency Contro
  • Python爬虫入门8:BeautifulSoup获取html标签相关属性

    前往老猿Python博客 https blog csdn net LaoYuanPython 一 引言 在上节 https blog csdn net LaoYuanPython article details 113091721 Pyth
  • 【神经网络搜索】DARTS: Differentiable Architecture Search

    GiantPandaCV DARTS将离散的搜索空间松弛 从而可以用梯度的方式进行优化 从而求解神经网络搜索问题 本文首发于GiantPandaCV 未经允许 不得转载 1 简介 此论文之前的NAS大部分都是使用强化学习或者进化算法等在离散
  • io回顾

    package test import java io 读取一个文件 并打印在控制台上 class FileReaderTest public static void main String args throws IOException
  • Golang 项目部署实战

    一直认为不懂部署的开发工程师不是好的开发工程师 以下以一些实例讲解自己在项目中的 Golang 后端部署的情况 一般部署脚本应该具有构建 启动 停止 回滚已经查看记录日志等功能 以下分别将这些功能以单个脚本的形式给出 当然也可以写成Make