Real World rc.d Script for Open Source Go Projects
#CI #CD #FreeBSD #Git #Go #Init
I host 33 web services on my personal servers. Ten of which are Go web services which I have created. They’re “open source.” In quotes as some services and their sources are obscured (I don’t care to document their uses). Managing more than a couple web services effectively needs some level of automation. Specifically around building and deploying the web services. Of which I handle with Git hooks and rc.d on FreeBSD.
On this blog you can find posts on minimal rc.d scripts and minimal CI/CD scripts but here I will show a full example I use across a number of open source Go projects that I think work well for general usage (and is used for this very blog).
I’ll begin with the post-update
Git hook.
#!/usr/bin/env sh
SERV='service_name'
TUSER='ssh_user'
THOST='ssh_target'
TPORT='ssh_port'
ssh -p $TPORT $TUSER@$THOST "service $SERV update ; echo deploy complete"
Pretty simple. You can see the hook does not build the software. It simply informs the target machine it should update. (Then assumes the update was performed successfully…).
The heavy lifting is on the rc.d script.
#!/bin/sh
# PROVIDE: servicename
# REQUIRE: LOGIN DAEMON NETWORKING
. /etc/rc.subr
name=servicename
rcvar=servicename_enable
extra_commands="update"
start_cmd="servicename_start"
stop_cmd="servicename_stop"
restart_cmd="servicename_restart"
update_cmd="servicename_update"
SERVICENAME="servicename"
SERVICENAME_BIN="/go/bin/$SERVICENAME"
SERVICENAME_GIT_SERVER="not.github.com"
SERVICENAME_GIT_USER="the_username"
SERVICENAME_GIT="$SERVICENAME_GIT_SERVER/$SERVICENAME_GIT_USER/$SERVICENAME"
SERVICENAME_GO="/usr/local/bin/go"
SERVICENAME_RUN="$SERVICENAME_BIN -port 80"
servicename_start()
{
if [ ! -f $SERVICENAME_BIN ] ; then
servicename_download
fi
daemon -r \
-p /var/log/servicename_child_pid \
-P /var/log/servicename_supervisor_pid \
-o /var/log/servicename \
$SERVICENAME_RUN
}
servicename_stop()
{
if [ -f /var/log/servicename_supervisor_pid ] ; then
cat /var/log/servicename_supervisor_pid | xargs kill -9
rm /var/log/servicename_supervisor_pid
fi
if [ -f /var/log/servicename_child_pid ] ; then
cat /var/log/servicename_child_pid | xargs kill -9
rm /var/log/servicename_child_pid
fi
}
servicename_restart()
{
servicename_stop
servicename_start
}
servicename_update()
{
servicename_download
servicename_restart
}
servicename_download()
{
env PATH="$PATH:/usr/local/bin" GOPROXY=direct $SERVICENAME_GO get -u $SERVICENAME_GIT@latest
}
load_rc_config $name
run_rc_command "$1"
This requires both Go and Git to be installed on the target machine.
When service servicename update
is issued the target machine will fetch the new Go source from Git, build the service, then restart the service.
EOF