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 apt
oder apt-get
0 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 apt
nicht 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 apt
Befehls 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 update
den 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 apt
zweiten 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 grep
eine 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.