Da ich immer häufiger Software verwende die in Go geschrieben ist und somit als Single-File veröffentlich wird, habe
ich mich entschlossen dafür ein Basis-Skript zu entwickeln, mit dem ich die Installation und weitere Aktualisierungen
durchführen kann. Als Basis diente ein Script von einem Kollegen.
Script-Datei
Zuerst hier einmal das Skript, eine detaliertere Beschreibung findet ihr im Anhang:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
| #!/usr/bin/bash
set -euo pipefail
### Configuration ###
target_architecture="linux-amd64"
prog_installdir="/usr/local/bin"
prog_link_name="<symlink-name>"
prog_service="${prog_link_name}.service"
git_server="code.example.com"
git_repo="<developer-name>/<project-name>"
### Buildes Configurations ###
git_repo_url="https://${git_server}/${git_repo}.git"
git_release_url="https://${git_server}/api/v1/repos/${git_repo}/releases/latest"
######################################################################
# Return 0 if service is running and 1 if it's not.
function check_service_running() {
echo "Checking service '$1' state..."
set +e
prog_service_state=$(systemctl is-active $1)
running=$?
set -e
if [ $running -eq 0 ]; then
echo "Service '$1' is running."
return 0
fi
echo "Service '$1' is not running (state: ${prog_service_state})."
return 1
}
######################################################################
### Main script
echo "=== Update Program to latest version ==="
pushd $prog_installdir
current_version=1.0.0
if [ -f $prog_link_name ]; then
current_version=$(./${prog_link_name} --version | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+" | sed -nr 's/\+/-/p')
fi
# Remember the old binary path to delete it later.
old_binary_path=$(realpath $prog_link_name)
echo "Currently installed version: $current_version (${prog_link_name} -> ${old_binary_path})"
release_tag=$(curl -s $git_release_url | jq .tag_name -r)
version=$release_tag
echo "Latest release tag on server: ${release_tag} => Program version: ${version}"
# Finish the script if there is no new version on the server.
if [[ $current_version = "$version" ]]; then
echo "Latest version is already installed - Nothing to do :-)"
service_running=$(check_service_running $prog_service)
if [[ $service_running ]]; then
exit 0
fi
exit 1
fi
# Build URLs
assets=$(curl -s $git_release_url | jq -c '.assets[] | select(.name | match("linux-amd64$"))')
binary_filename=$(echo $assets | jq .name -r)
download_url=$(echo $assets | jq .browser_download_url -r)
echo "Binary name. ${binary_filename}"
echo "Download URL: ${download_url}"
echo
# Remove binary if it exists, download new binary and set it's executable flag.
echo "Downloading new version..."
rm -f "$binary_filename"
curl -JOL "$download_url"
chmod +x "$binary_filename"
# Update symlink and get the new full path to the binary.
echo "Linking ${prog_link_name} to new binary ${binary_filename}..."
ln -sf "$binary_filename" $prog_link_name
new_binary_path=$(realpath $prog_link_name)
# Restart the service to use the new binary.
echo "Restarting service..."
systemctl restart $prog_service
# Check if it's running successfully.
service_running=$(check_service_running $prog_service)
if [[ $service_running ]]; then
echo "Success!"
if [[ $new_binary_path = "$old_binary_path" ]]; then
echo "Binary path unchanged - don't delete old binary."
else
echo "Delete old binary ${old_binary_path}..."
rm "${old_binary_path}"
fi
exit 0
else
echo ":-("
exit 1
fi
|
Parameter
Im ersten Teil werden sind die Konfiguration, die anzupassen sind. Die Architektur und das Installationsverzeichnis sollte
meist passen und muss nicht verändert werden.
Der prog_link_name
definiert den Namen unter dem das Program im System registriet wird. Hierfür wird ein symbolischer
Link auf die Datei mit der Versionsnummer hinterlegt. Hermit können die Dateien einfacher ausgetauscht werden.
Beim prog_installdir
wird die ablage der Binärdateien definiert, diese sollte nicht verändert werden.
Mit git_server
und git_repo
definiert man den Server und die das Projekt, in dem die Software gepflegt und die Release
Versionen freigegeben werden.
Ablauf
Das Script selbst läuft wie folgt ab:
- Die aktuell installierte Version wird mit der aktuell freigegebenen Version vergleichen
- Der aktuelle Binärpfad wird gespeichert für späteres löschen
- Sollte keine neuere Version vorhanden sein, ist das Skript fertig
- Die neue Version wird ins Installationsverzeichnis heruntergeladen, als ausführbar gekenzeichnet
- Der Link wird auf die neue Version umgestellt
- Der Dienst wird neugstartet und überprüft ob er läuft
- Wenn der Dienst erfolgreich gestartet wurde, wird die Binärdatei der alten Version entfernt