Bash Shell-Skripte: Obwohl apt-get update fehlgeschlagen ist, ist der Exit-Status 0. Schreiben automatischer Update-Skripte unter Verwendung von Exit-Status

Bash Shell-Skripte: Obwohl apt-get update fehlgeschlagen ist, ist der Exit-Status 0. Schreiben automatischer Update-Skripte unter Verwendung von Exit-Status

Ich versuche, ein automatisches Update- und Upgrade-Skript zu schreiben.

Ich möchte den Exit-Status der Befehlsausführung nutzen,

aber selbst wenn der Befehl apt-get update fehlschlägt, gibt er den Exit-Status 0 zurück.

Daher kann mein Skript seinen Zweck nicht erfüllen.

FRAGEN===========

Warum gibt apt-get update 0 zurück, ich möchte aber bei einem fehlgeschlagenen Befehl andere Zahlen als 0 erhalten?

Und wie kann ich mein Skript ändern, damit es seinen Zweck erfüllt?

=====================

Vielen Dank fürs Lesen!

Hier ist der Aktualisierungsteil meines Skripts;

#!/bin/bash -x 

### Variables
count=
command_result=""

### Main

echo "$(LC_TIME=en_US.UTF-8 date)" >> log_update

until [ "$count" = "10" ] || [ "$command_result" = "done" ]; do

    sudo apt-get update

    if [ "$?" = "0" ]; then
        echo "Update succeeds." >> ~/log_update
        command_result="done"
    fi

    count=$((count + 1)) 

done

if [ "$command" != "done" ]; then
    echo "Time Out: Update FAILED! Solve Problem." >> log_update
fi

Antwort1

Um zu verstehen, warum aptoder apt-get0 zurückgibt, selbst wenn ein Fehler auftritt, sollten Sie zunächst wissen, dass diese Befehle auch ein Programm sind, das von einem Programmierer entwickelt wurde. Daher werden die an das Terminal zurückgegebenen Werte auch vom Entwickler des Programms festgelegt.

Der einzige Fall, in dem es meines Wissens aptnicht funktioniert, ist die Ausführung ohne. sudo
Hier ist ein Ausschnitt, in dem apt ohne Superuser-Berechtigungen ausgeführt wird:

mars@HP-Notebook:~/Desktop/Practice/cpp$ apt update
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)
W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
100

Wie Sie sehen, ist der Exit-Code nicht 0. Daraus können wir schließen, dass der Befehl oder das Programm nicht ausgeführt wurde.
Betrachten wir einen anderen Fall, in dem keine Internetverbindung besteht:

mars@HP-Notebook:~/Desktop/Practice/cpp$ sudo apt update
Err:1 http://security.ubuntu.com/ubuntu bionic-security InRelease
  Could not resolve 'security.ubuntu.com'
Err:2 http://dl.google.com/linux/chrome/deb stable InRelease                                                   
  Could not resolve 'dl.google.com'
Err:3 http://in.archive.ubuntu.com/ubuntu bionic InRelease                                                     
  Could not resolve 'in.archive.ubuntu.com'
Err:4 https://download.sublimetext.com apt/stable/ InRelease                     
  Could not resolve 'download.sublimetext.com'
Err:5 http://in.archive.ubuntu.com/ubuntu bionic-updates InRelease
  Could not resolve 'in.archive.ubuntu.com'
Err:6 http://in.archive.ubuntu.com/ubuntu bionic-backports InRelease
  Could not resolve 'in.archive.ubuntu.com'
Reading package lists... Done
Building dependency tree       
Reading state information... Done
All packages are up to date.
W: Failed to fetch http://in.archive.ubuntu.com/ubuntu/dists/bionic/InRelease  Could not resolve 'in.archive.ubuntu.com'
W: Failed to fetch http://in.archive.ubuntu.com/ubuntu/dists/bionic-updates/InRelease  Could not resolve 'in.archive.ubuntu.com'
W: Failed to fetch http://in.archive.ubuntu.com/ubuntu/dists/bionic-backports/InRelease  Could not resolve 'in.archive.ubuntu.com'
W: Failed to fetch http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease  Could not resolve 'security.ubuntu.com'
W: Failed to fetch https://download.sublimetext.com/apt/stable/InRelease  Could not resolve 'download.sublimetext.com'
W: Failed to fetch http://dl.google.com/linux/chrome/deb/dists/stable/InRelease  Could not resolve 'dl.google.com'
W: Some index files failed to download. They have been ignored, or old ones used instead.
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0

Wie Sie sehen, lautet der Exit-Code 0, obwohl ein Fehler aufgetreten ist. Der Grund dafür ist, dass das Programm oder der Befehl erfolgreich ausgeführt wurde. Allerdings konnten die Paketlisten für Upgrades von Paketen, die aktualisiert werden müssen, nicht aktualisiert werden.

Die einzige Erklärung dafür ist, dass der Entwickler des aptBefehls das fehlgeschlagene Aktualisieren der Paketliste nicht als Fehler betrachtete, um den Befehl selbst zu stoppen und einen Fehler-Exit-Statuscode zurückzugeben. Stattdessen gibt der Befehl nach der Ausführung Warnungen aus.

Zum besseren Verständnis werde ich ein Beispiel eines C-Programms verwenden:

#include<stdio.h>

int main(int argc, char *argv[]) {
    if(argc==2) 
        printf("Welcome Master %s\n", argv[1]);
    else {
        fprintf(stderr, "Usage : %s <name>\n", argv[0]);
        return 1;
    }
    return 0;
}

Ausgabe:

mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman
Usage : ./batman <name>
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
1
mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman Bruce
Welcome Master Bruce
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0

Wie Sie sehen, gibt es zwei verschiedene Exit-Statuscodes, da ich als Programmierer der Ansicht bin, dass die Ausführung eines Befehls ohne Argument ein Fehler ist und mit dem Exit-Code „1“ beendet werden sollte. (Ich könnte jeden beliebigen Wert wählen.) Und wenn der Befehl erfolgreich ausgeführt wurde, gebe ich als Exit-Statuscode „0“ zurück, was bedeutet, dass kein Fehler aufgetreten ist.

Nehmen wir ein anderes Beispiel:

#include<stdio.h>

int main(int argc, char *argv[]) {
    if(argc==2) 
        printf("Welcome Master %s\n", argv[1]);
    else
        printf("ERROR!!\nUsage : %s <name>\n", argv[0]);

    return 0;
}

Ausgabe:

mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman_error 
ERROR!!
Usage : ./batman_error <name>
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0
mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman_error Bruce
Welcome Master Bruce
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0

Wieder dasselbe Programm, aber diesmal hat der Programmierer (also ich) nicht daran gedacht, das Programm mit einem anderen Exit-Statuscode zu beenden. Obwohl das Terminal also eine Fehlerausgabe ausgibt, ist der Exit-Statuscode „0“.

Abschluss

Es liegt in der Verantwortung des Programmentwicklers, welcher Wert (also der Exit-Statuscode) je nach Situation zurückgegeben werden soll.
Ich hoffe, dies verdeutlicht das Konzept des Exit-Statuscodes.

Vorschlag für Ihr Bash-Skript

Ich habe gesehen, dass Sie eine Schleife verwenden, die 10 Mal versucht, apt updateden Befehl auszuführen, wenn er nicht erfolgreich ausgeführt wurde. Ehrlich gesagt, wenn es beim ersten Mal nicht funktioniert hat, wird es auch die nächsten 9 Male nicht funktionieren. Daher ist das Erstellen einer Schleife einfach sinnlos.

Wenn Sie nun nach einem Fehler suchen möchten, verwenden Sie verschachtelte if-else-Bedingungen. Sie können auf der ersten Ebene nach einem Statuscode suchen und auf der aptzweiten Ebene nach einem Fehler bei der Ausführung (d. h. mit Exitcode „0“). Dazu können Sie etwas wie Folgendes verwenden:

sudo apt update | grep "Err"

Wenn grepeine Zeile abgerufen werden konnte, speichern Sie dies als Fehler in Ihrer Protokolldatei, andernfalls war die Aktualisierung erfolgreich.

Antwort2

Warum gibt apt-get update 0 zurück, ich möchte aber bei einem fehlgeschlagenen Befehl andere Zahlen als 0 erhalten?

apt betrachtet vorübergehende Netzwerkfehler als Warnungen (keine Fehler), die keinen Exit-Code ungleich Null verursachen. Siehedieser Quellcode.

Und wie kann ich mein Skript ändern, damit es seinen Zweck erfüllt?

Im oben verlinkten Quellcode werden Sie eine weitere Klausel in der Bedingung ( errorMode != ErrorMode::Any) bemerken. Um Warnungen als Fehler zu behandeln, versuchen Sie Folgendes:

# apt -o 'APT::Update::Error-Mode=any' update

Dies führt dazu, dass Apt Warnungen als Fehler behandelt. Vorübergehende Netzwerkfehler führen dann dazu, dass Apt mit einem Wert ungleich Null beendet wird.

Sie können dies bei Bedarf stattdessen zu apt conf hinzufügen.

verwandte Informationen