Ich untersuche den Inhalt dieser Preinst- Datei, die das Skript ausführt, bevor dieses Paket aus seiner Debian-Archivdatei (.deb) entpackt wird.
Das Skript hat den folgenden Code:
#!/bin/bash
set -e
# Automatically added by dh_installinit
if [ "$1" = install ]; then
if [ -d /usr/share/MyApplicationName ]; then
echo "MyApplicationName is just installed"
return 1
fi
rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf
rm -Rf $HOME/.local/share/file-manager/actions/*
fi
# End automatically added section
Meine erste Frage betrifft die Zeile:
set -e
Ich denke, dass der Rest des Skripts ziemlich einfach ist: Es prüft, ob der Debian / Ubuntu-Paketmanager einen Installationsvorgang ausführt. Wenn dies der Fall ist, wird überprüft, ob meine Anwendung gerade auf dem System installiert wurde. Wenn dies der Fall ist , druckt das Skript die Meldung "MyApplicationName ist gerade installiert" und endet ( return 1
bedeutet, dass dies mit einem "Fehler" endet, nicht wahr ?).
Wenn der Benutzer das Debian / Ubuntu-Paketsystem auffordert, mein Paket zu installieren, löscht das Skript auch zwei Verzeichnisse.
Ist das richtig oder fehlt mir etwas?
man set
set +e
Antworten:
Von
help set
:Aber es wird von einigen als schlechte Praxis angesehen (Bash-FAQ- und IRC-Freenode-#Bash-FAQ-Autoren). Es wird empfohlen, Folgendes zu verwenden:
do_something
Funktion ausführen , wenn Fehler auftreten.Siehe http://mywiki.wooledge.org/BashFAQ/105
quelle
trap 'exit' ERR
ERR
Falle wird nicht von Shell - Funktionen geerbt, wenn Sie also Funktionen haben,set -o errtrace
oderset -E
werden Sie nur die Falle gestellt , damit einmal und es global gelten.trap 'exit' ERR
tun etwas andersset -e
?set -e
Stoppt die Ausführung eines Skripts, wenn ein Befehl oder eine Pipeline einen Fehler aufweist. Dies ist das Gegenteil des Standardverhaltens der Shell, bei dem Fehler in Skripten ignoriert werden. Geben Siehelp set
ein Terminal ein, um die Dokumentation zu diesem integrierten Befehl anzuzeigen.quelle
set -o pipefail
der Fehler weitergegeben werden können, sodass der Rückgabewert des Pipeline-Befehls ungleich Null ist, wenn einer der vorhergehenden Befehle mit einem Status ungleich Null beendet wird.-o pipefail
dies nur bedeutet, dass der Exit-Status des ersten Befehls ungleich Null (dh Fehler in-o errexit
Begriffen) der Pipeline bis zum Ende weitergegeben wird. Die verbleibenden Befehle in der Pipeline noch laufen , auch mitset -o errexit
. Zum Beispiel:echo success | cat - <(echo piping); echo continues
, woecho success
einen erfolgreichen darstellt, aber fehlbar Befehl, drucktsuccess
,piping
undcontinues
, aberfalse | cat - <(echo piping); echo continues
mit ,false
die den Befehl jetzt erroring still, drucken nochpiping
vor dem Verlassen.Wie pro bash - Das Set Builtin manuell, wenn
-e
/errexit
festgelegt ist, die Shell beendet sofort , wenn eine Rohrleitung aus einem einzigen aus einfachen Befehl , eine Liste oder eine Verbindung Befehl zurückkehrt ein Nicht-Null - Status.Standardmäßig ist der Exit-Status einer Pipeline der Exit-Status des letzten Befehls in der Pipeline, sofern die
pipefail
Option nicht aktiviert ist (standardmäßig deaktiviert).In diesem Fall wird der Rückgabestatus der Pipeline des letzten (am weitesten rechts stehenden) Befehls mit einem Status ungleich Null oder Null, wenn alle Befehle erfolgreich beendet wurden.
Wenn Sie beim Beenden etwas ausführen möchten, definieren Sie
trap
beispielsweise Folgendes :Wo
onexit
ist Ihre Funktion, um beim Beenden etwas zu tun, wie unten, wo die einfache Stapelverfolgung gedruckt wird :Es gibt ähnliche Option
-E
/errtrace
das würde Fall auf ERR statt, zum Beispiel:Beispiele
Beispiel für den Nullstatus:
Beispiel für einen Status ungleich Null:
Beispiele für das Negieren von Status:
Test mit
pipefail
Deaktivierung:Test mit
pipefail
aktiviertem:quelle
Ich habe diesen Beitrag gefunden, als ich versucht habe, den Exit-Status für ein Skript zu ermitteln, das aufgrund von a abgebrochen wurde
set -e
. Die Antwort erschien mir nicht offensichtlich; daher diese Antwort. Grundsätzlich wirdset -e
die Ausführung eines Befehls (z. B. eines Shell-Skripts) abgebrochen und der Exit-Statuscode des fehlgeschlagenen Befehls zurückgegeben (dh das innere Skript, nicht das äußere Skript) .Angenommen, ich habe das Shell-Skript
outer-test.sh
:Der Code für
inner-test.sh
lautet:Wenn ich
outer-script.sh
von der Befehlszeile aus starte, endet mein äußeres Skript mit dem Exit-Code des inneren Skripts:quelle
Ich glaube, die Absicht ist, dass das betreffende Skript schnell fehlschlägt.
Um dies selbst zu testen, geben Sie einfach
set -e
an einer Bash-Eingabeaufforderung ein. Versuchen Sie jetzt zu laufenls
. Sie erhalten eine Verzeichnisliste. Geben Sie nun einlsd
. Dieser Befehl wird nicht erkannt und gibt einen Fehlercode zurück. Daher wird Ihre Bash-Eingabeaufforderung (aufgrund vonset -e
) geschlossen.Um dies im Kontext eines 'Skripts' zu verstehen, verwenden Sie dieses einfache Skript:
Wenn Sie es so ausführen, wie es ist, erhalten Sie die Verzeichnisliste aus
ls
der letzten Zeile. Wenn Sie das auskommentierenset -e
und erneut ausführen, wird die Verzeichnisliste nicht angezeigt, da bash die Verarbeitung beendet, sobald der Fehler von auftrittlsd
.quelle
Dies ist eine alte Frage, aber keine der Antworten hier beschreibt die Verwendung von
set -e
akaset -o errexit
in Debian-Paketsammlungsskripten. Die Verwendung dieser Option ist in diesen Skripten gemäß der Debian-Richtlinie obligatorisch . Die Absicht ist offenbar, die Möglichkeit eines unbehandelten Fehlerzustands zu vermeiden.In der Praxis bedeutet dies, dass Sie verstehen müssen, unter welchen Bedingungen die von Ihnen ausgeführten Befehle einen Fehler zurückgeben können, und jeden dieser Fehler explizit behandeln müssen.
Häufige Fallstricke sind z. B.
diff
(gibt einen Fehler zurück, wenn es einen Unterschied gibt) undgrep
(gibt einen Fehler zurück, wenn keine Übereinstimmung vorliegt). Sie können die Fehler durch explizite Behandlung vermeiden:(Beachten Sie auch, wie wir darauf achten, den Namen des aktuellen Skripts in die Nachricht aufzunehmen und Diagnosemeldungen anstelle der Standardausgabe in den Standardfehler zu schreiben.)
Wenn keine explizite Behandlung wirklich notwendig oder nützlich ist, tun Sie explizit nichts:
(Die Verwendung des
:
No-Op-Befehls der Shell ist etwas unklar, wird aber häufig verwendet.)Nur um es noch einmal zu wiederholen,
ist eine Abkürzung für
dh wir sagen ausdrücklich,
other
sollte ausgeführt werden, wenn und nur wennsomething
fehlschlägt. Die Langschriftif
(und andere Shell - Flusskontrolle Aussagen wiewhile
,until
) ist auch ein gültiger Weg , um einen Fehler zu behandeln (in der Tat, wenn es mit nicht, Shell - Skripteset -e
nie Flusskontrolle Aussagen enthalten könnte!)Und nur um genau zu sein, würde in Abwesenheit eines solchen
set -e
Handlers das gesamte Skript sofort mit einem Fehler fehlschlagen, wenndiff
ein Unterschied festgestellt wird oder wenngrep
keine Übereinstimmung gefunden wird.Andererseits erzeugen einige Befehle keinen Fehler-Exit-Status, wenn Sie dies wünschen. Häufig problematische Befehle sind
find
(der Exit-Status gibt nicht an, ob tatsächlich Dateien gefunden wurden) undsed
(Der Exit-Status zeigt nicht an, ob das Skript Eingaben empfangen oder tatsächlich erfolgreich Befehle ausgeführt hat). In einigen Szenarien besteht eine einfache Wache darin, zu einem Befehl zu leiten, der schreit, wenn keine Ausgabe erfolgt:Es ist zu beachten, dass der Exit-Status einer Pipeline der Exit-Status des letzten Befehls in dieser Pipeline ist. Die obigen Befehle maskieren also den Status von
find
und vollständigsed
und sagen Ihnen nur, ob diesgrep
letztendlich erfolgreich war.(Bash hat es natürlich getan
set -o pipefail
; Debian-Paketskripte können jedoch keine Bash-Funktionen verwenden. Die Richtlinie schreibt die Verwendung von POSIXsh
für diese Skripte fest vor, obwohl dies nicht immer der Fall war.)In vielen Situationen ist dies beim defensiven Codieren separat zu beachten. Manchmal müssen Sie z. B. eine temporäre Datei durchgehen, um zu sehen, ob der Befehl, der diese Ausgabe erzeugt hat, erfolgreich beendet wurde, selbst wenn Sie sonst aufgrund der Redewendung und Zweckmäßigkeit angewiesen werden, eine Shell-Pipeline zu verwenden.
quelle
quelle