Essential Bash Scripts for Deploying Golang Backend Services
This guide walks through a complete set of Bash scripts for building, starting, stopping, upgrading, and rolling back a Go backend application, explains the required directory layout, and highlights signal handling to ensure reliable deployments.
Why Deployment Scripts Matter
Even seasoned developers need reliable deployment tools; a good set of scripts can automate building, launching, stopping, rolling back, and logging for Go backend services.
Directory Layout
All scripts reside in a single folder alongside a bin directory for compiled binaries and an app.log file for runtime logs.
bin # directory for compiled binaries
app.log # runtime log file
log.sh # tail logs
build.sh # compile the project
run.sh # launch a binary in background
start.sh # start latest version, backup previous
shutdown.sh# stop the running service
rollback.sh# revert to previous versionlog.sh
tail -f -n 200 app.log # show the last 200 lines in real timebuild.sh
The script sets project paths, selects a Git branch, pulls the latest code, builds the Go binary, and copies the result to a version‑specific file.
#!/bin/bash
baseProjectDir="/go/src/monitor"
targetDir="bin"
branch="master"
pwd=$(pwd)
targetFile=$(basename $pwd)
buildPkg="monitor"
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
# launch the binary in background and redirect output to app.log
nohup ./$1 >> app.log &start.sh
Stops any existing version, optionally forces termination, backs up the old binary, replaces it with the newly built one, and starts the service.
#!/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
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
echo "Starting..."
./run.sh $target
echo "Done"shutdown.sh
Identical to the stop portion of start.sh but does not perform an upgrade.
#!/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
Stops the current binary, restores the previously backed‑up version, and restarts it.
#!/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 $(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
if [ -f "${target}-backup" ]; then
echo "Rolling back..."
rm -f "$target"
mv ${target}-backup $target
echo "Rollback Complete"
fi
echo "Starting..."
./run.sh $target
echo "Done"Signal Handling in Go
When kill -s 2 is used, the Go program must listen for os.Interrupt (SIGINT) to exit cleanly. A minimal example:
package main
import (
"log"
"os"
"os/signal"
"github.com/robfig/cron"
)
func main() {
c := cron.New()
c.AddFunc("*/3 * * * * ?", func(){ log.Println("cron running") })
c.Start()
go signalListen()
select {}
}
func signalListen() {
ch := make(chan os.Signal)
signal.Notify(ch, os.Interrupt, os.Kill)
for {
<-ch
os.Exit(0)
}
}These scripts together provide a lightweight, reproducible deployment workflow for Go backend services without requiring external tools like Make or CI pipelines.
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.
