Mastering Go Backend Deployment: Build, Run, and Rollback Scripts Explained
This guide walks through a complete set of Bash scripts for building, starting, stopping, rolling back, and monitoring a Go backend service, explains signal handling in Go, and provides a curated list of useful open‑source Go projects and libraries.
Introduction
Deploying a Go backend reliably requires a set of scripts that can build, start, stop, roll back, and view logs of the service. The following examples show how to organize these scripts in a single directory and automate common deployment tasks.
Directory Layout
Create the following files in one folder:
bin # Directory for compiled binaries after each build
app.log # Log file for runtime output
log.sh # Tail the last 200 lines of the log
build.sh # Build the Go project
run.sh # Run a specific binary in background
start.sh # Start the latest version, backing up the previous one
shutdown.sh# Stop the running service
rollback.sh# Roll back to the previous versionScript Details
log.sh
tail -f -n 200 app.log # Show the last 200 lines of the log in real timebuild.sh
#!/bin/bash
baseProjectDir="/go/src/monitor" # Project path inside GOPATH
targetDir="bin" # Directory for compiled binaries
branch="master"
pwd=$(pwd)
targetFile=$(basename $pwd)
buildPkg="monitor"
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 1
fi
echo "All Complete"run.sh
#!/bin/bash
# Run the binary in background and redirect output to app.log
nohup ./$1 >> app.log &start.sh
#!/bin/bash
pwd=$(pwd)
target=$(basename $pwd)
# Kill existing process if any
pid=$(ps -C ${target} -o pid=)
if [ -n "$pid" ]; then
echo "Stopping old version, PID: ${pid}"
if [ "$1" = "-f" ]; then
echo "Force shutdown..."
kill -9 $(ps -C ${target} -o pid=)
else
kill -s 2 $(ps -C ${target} -o pid=)
fi
# Wait for process to exit
while [ -n "$(ps -C ${target} -o pid=)" ]; do
sleep 1
done
fi
# Upgrade if new binary exists
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
# Start the new version
echo "Starting..."
./run.sh ${target}
echo "Done"shutdown.sh
#!/bin/bash
pwd=$(pwd)
target=$(basename $pwd)
pid=$(ps -C ${target} -o pid=)
if [ -n "$pid" ]; then
echo "Stopping old version, PID: ${pid}"
if [ "$1" = "-f" ]; then
echo "Force shutdown..."
kill -9 $(ps -C ${target} -o pid=)
else
kill -s 2 $(ps -C ${target} -o pid=)
fi
while [ -n "$(ps -C ${target} -o pid=)" ]; do
sleep 1
done
fi
echo "Done"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
echo "Force shutdown..."
kill $(ps -C ${target} -o pid=)
else
kill -s 2 $(ps -C ${target} -o pid=)
fi
while [ -n "$(ps -C ${target} -o pid=)" ]; do
sleep 1
done
fi
# Rollback if backup exists
if [ -f "${target}-backup" ]; then
echo "Rolling back..."
rm -f "${target}"
mv "${target}-backup" "${target}"
echo "Rollback Complete"
fi
# Start the restored version
echo "Starting..."
./run.sh ${target}
echo "Done"Signal Handling in Go
When using kill -s 2 (SIGINT), the Go program should listen for the interrupt signal to exit gracefully:
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)
signal.Notify(c, os.Interrupt, os.Kill)
for {
<-c
os.Exit(0)
}
}Additional Go Open‑Source Resources
The author also compiled a list of useful Go projects and libraries for further learning:
Console progress bar
NutsDB
Microsoft Go tutorial
Batch rename tool
Dapr
Didi open‑source projects
Go generics
Chinese open‑source monitoring tools
SQL utilities
sqlx
Go form validator
Eye‑following mouse cursor
Fiber browser
Frontend‑to‑Go framework preferences
Go distributed file system
Image server
Go live‑streaming project
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Go Development Architecture Practice
Daily sharing of Golang-related technical articles, practical resources, language news, tutorials, real-world projects, and more. Looking forward to growing together. Let's go!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
