Bash Update-Script: Erkennung der Software-Version optimieren

kachiri

Fleet Admiral
Registriert
Apr. 2011
Beiträge
15.366
Ich habe auf meinem Uberspace eine Ghost-Instanz installiert, die ich regelmäßig mit einem einfachen Bash-Script update. Das Script wurde von verschiedenen Uberspace-Usern geschrieben. Ich habe das gesamte Script einmal beigefügt.

Bevor die Update-Schritte ausgeführt werden, gleicht das Script die installierte Version mit der verfügbaren Version im GitHub-Repo von den Entwicklern ab. Nur wenn die installierte Version kleiner als die verfügbare Version ist, werden die weiteren Befehle ausgeführt.

Das hat bisher auch wunderbar funktioniert... Nun ist die Versionsnummer allerdings von 4.9.x auf 4.10.x gesprungen. Das Script meldet mir, dass Ghost bereits auf dem aktuellsten Stand ist.

Jetzt fehlt mir hier tatsächlich auch ein wenig der Hintergrund, aber ich kann zumindest nachvollziehen, dass das Script die 10 eben nicht als solche erkennt, sondern schlicht eine 9 und eine 1 sieht. Die 1 ist kleiner als 9, also ist die installierte Version aktuell.
An und für sich ist das kein großes Drama. Ich könnte die Update-Schritte einmalig "manuell" ausführen und bei den folgenden Updates wird diese Logik wieder kein Problem darstellen (selbst bei einem Sprung von 4.19.x zu 4.20.x zu 4.31.x)

Aber vielleicht lässt sich das Script (who knows, wann eine Version 5.9 zu 5.10 wechselt ;)) mit 1-2 einfachen Griffen auch schon optimieren. Gerne auch Hinweise und/oder kleine Erklärungen, damit ich die Logik dahinter verstehe.

Danke schon einmal!

Bash:
#!/bin/bash
#set -v
GHOSTDIR=~/webapps/ghost
PACKAGE_VERSION_OLD=$(sed -nE 's/^\s*"version": "(.*?)",$/\1/p' $GHOSTDIR/current/package.json)
CURRENT_GHOST=$(curl -s https://api.github.com/repos/TryGhost/Ghost/releases/latest | grep \"name\": | head -n 1 | cut -d '"' -f 4)
CURRENT_GHOST_DOWNLOAD=$(curl -s https://api.github.com/repos/TryGhost/Ghost/releases/latest | grep browser_download_url | cut -d '"' -f 4)
CURRENT_GHOST_FILE=$(echo $CURRENT_GHOST_DOWNLOAD | sed 's:.*/::')

echo "Installierte Version von Ghost: $PACKAGE_VERSION_OLD"
echo " Verfuegbare Version von Ghost: $CURRENT_GHOST"
cd $GHOSTDIR
if [[ $CURRENT_GHOST > $PACKAGE_VERSION_OLD ]]
then
  read -r -p "Soll Ghost jetzt von Version $PACKAGE_VERSION_OLD auf $CURRENT_GHOST aktualisiert werden? [J/n] " response
  if [[ $response =~ ^([jJ][aA]|[jJ]|"")$ ]]
  then
    echo "Pruefe auf Aktualisierung von npm..."
    echo "Node.js version: $( node -v)" && echo "Bisherige npm version: $(npm -v)"
    npm install -g npm
    echo "Neue npm version: $(npm -v)"
    echo "Pruefe auf Aktualisierung von knex-migrator..."
    echo "Bisherige knex-migrator version: $(knex-migrator -v)"
    npm install -g knex-migrator
    echo "Neue knex-migrator version: $(knex-migrator -v)"
    echo "Pruefe auf Aktualisierung von yarn..."
    echo "Bisherige yarn version: $(yarn --version)"
    npm install -g yarn
    echo "Neue yarn version: $(yarn --version)"
    echo "Ghost $CURRENT_GHOST wird heruntergeladen und entpackt..."
    cd $GHOSTDIR/versions/
    curl -LOk $CURRENT_GHOST_DOWNLOAD
    unzip $GHOSTDIR/versions/$CURRENT_GHOST_FILE -d $CURRENT_GHOST
    rm $GHOSTDIR/versions/$CURRENT_GHOST_FILE
    echo "Ghost wird jetzt aktualisiert..."
    cd $GHOSTDIR/versions/$CURRENT_GHOST
    yarn install --production
    echo "Die Datenbank von Ghost wird auf die neue Version migriert..."
    cd $GHOSTDIR
    NODE_ENV=production knex-migrator migrate --mgpath $GHOSTDIR/versions/$CURRENT_GHOST
    ln -sfn $GHOSTDIR/versions/$CURRENT_GHOST $GHOSTDIR/current
    PACKAGE_VERSION=$(sed -nE 's/^\s*"version": "(.*?)",$/\1/p' $GHOSTDIR/current/package.json)
    echo "Ghost wurde von Version $PACKAGE_VERSION_OLD auf Version $PACKAGE_VERSION aktualisiert und wird neu gestartet. Dies kann ein paar Sekunden dauern..."
    supervisorctl restart ghost
    supervisorctl status
    dir=$(cd $GHOSTDIR/versions && ls  -1rd */ | tail -n +4)
    keep=$(cd $GHOSTDIR/versions && ls -1rd */ | head -3)
    echo "Loesche alte Versionen" && echo $dir && echo "Behalte die letzten drei Versionen" && echo $keep
    cd $GHOSTDIR/versions && ls -1rd */ | tail -n +4 | xargs rm -rf
    echo "Bei Fehlern Logfile ueberpruefen: 'supervisorctl tail ghost'"
    echo "Zum Zuruecksetzen auf Ghost $PACKAGE_VERSION_OLD folgenden Befehl ausfuehren: 'ln -sfn $GHOSTDIR/versions/$PACKAGE_VERSION_OLD $GHOSTDIR/current' und dann per 'supervisorctl restart ghost' neustarten"
  else
    echo "-> Ghost wird nicht aktualisiert"
  fi
else
  echo "-> Ghost ist bereits auf dem aktuellen Stand, keine Aktualisierung notwendig"
fi
 
Der Klassiker wäre String splitten, einzelne Bestandteile in Integer zu konvertieren und dann zu zu checken.
Also quasi Major-, Minorversion und Buildnumber extrahieren. Dann Vergleich Major, dann Minor, dann Build
 
  • Gefällt mir
Reaktionen: BeBur und xone92
Alles zu kompliziert...
Die Krux ist, dass Du mit Deinem Test auf Versionsnummer einen String-Vergleich machst.
kachiri schrieb:
if [[ $CURRENT_GHOST > $PACKAGE_VERSION_OLD ]]
Falls (falls!) die Versionsnummer tatsächlich numerisch ist und keine Zeichenkette, kannst Du einen Zahlenvergleich machen mit
Code:
-lt
-gt

Vergleiche
Code:
[[ 199 < 20 ]]
mit
Code:
[[ 199 -lt 20 ]]
(das Ergebnis z.B. mit
Code:
echo $?
abfragen, 1 ist "false")

Deine Zeile könnte also lauten
Code:
if [[ $CURRENT_GHOST -gt $PACKAGE_VERSION_OLD ]]

Disclaimer:
Falls keine reine Zahl verglichen wird, geht's natürlich nur kompliziert.
 
Wie wäre es mit != in Zeile 12 statt >?
Eure Regex sehen alle irgendwie seltsam aus, aber vllt liegt das an der Uhrzeit :D.
 

Ähnliche Themen

Zurück
Oben