linux - not - ls ubuntu




Was bedeutet a! vor einem befehl in der shell? (2)

Die Frage steht im Titel. Was ist der Zweck eines Shell-Befehls (Teil eines Shell-Skripts), der mit einem Ausrufezeichen beginnt? Konkretes Beispiel:

In foo.sh:

#!/usr/bin/env bash
set -e
! docker stop foo
! docker rm -f foo
# ... other stuff

Ich weiß, dass ohne das Leerzeichen das Ausrufezeichen für Ersetzungen der Historie verwendet wird und ! <expression> ! <expression> laut Manpage " True if expr is false " ausgewertet werden. Aber im Beispielkontext ergibt das für mich keinen Sinn.


"!" Bedeutet "nicht", wenn Sie es also vor einen Befehl stellen und "$?" Es wird eine 1 zurückgeben. Dies bedeutet, dass es fehlgeschlagen ist, anstatt einer 0, was Erfolg bedeutet.


TL; DR: Dies set -e Flag set -e in der spezifischen Zeile, in der Sie es verwenden.

Hinzufügen zu hek2mgls richtiger und nützlicher Antwort .

Du hast:

set -e
! command

Bash Reference Manual → Pipelines beschreibt:

Jeder Befehl in einer Pipeline wird in einer eigenen Subshell ausgeführt. Der Beendigungsstatus einer Pipeline ist der Beendigungsstatus des letzten Befehls in der Pipeline (...). Wenn das reservierte Wort '!' vor der Pipeline ist der Exit-Status die logische Negation des Exit-Status wie oben beschrieben. Die Shell wartet, bis alle Befehle in der Pipeline beendet sind, bevor sie einen Wert zurückgibt.

Das bedeutet das ! Vor einem Befehl wird dessen Exit-Status negiert:

$ echo 23
23
$ echo $?
0
                # But
$ ! echo 23
23
$ echo $?
1

Oder:

$ echo 23 && echo "true" || echo "fail"
23
true
$ ! echo 23 && echo "true" || echo "fail"
23
fail

Der Exit-Status ist in vielerlei Hinsicht nützlich. set -e das Skript in Ihrem Skript zusammen mit set -e wird es beendet, wenn ein Befehl einen Status ungleich Null zurückgibt.

Wenn Sie also:

set -e
command1
command2

Wenn command1 einen Status ungleich null zurückgibt, wird das Skript beendet und command2 nicht mit command2 .

Es gibt jedoch auch einen interessanten Punkt zu erwähnen, der in 4.3.1 Das Set Builtin beschrieben ist :

-e

Beenden Sie sofort, wenn eine Pipeline (siehe Pipelines), die aus einem einzelnen einfachen Befehl (siehe Simple Commands), einer Liste (siehe Lists) oder einem zusammengesetzten Befehl (siehe Compound Commands) bestehen kann, einen Nicht-Null-Status zurückgibt. Die Shell wird nicht beendet, wenn der fehlgeschlagene Befehl Teil der Befehlsliste ist, die unmittelbar auf ein while- oder until-Schlüsselwort folgt, Teil des Tests in einer if-Anweisung ist, Teil eines Befehls, der in einem && oder || ausgeführt wird Liste mit Ausnahme des Befehls nach dem letzten && oder ||, eines beliebigen Befehls in einer Pipeline außer dem letzten, oder wenn der Rückgabestatus des Befehls mit invertiert wird! . Wenn ein zusammengesetzter Befehl außer einer Subshell einen Status ungleich Null zurückgibt, weil ein Befehl fehlgeschlagen ist, während -e ignoriert wurde, wird die Shell nicht beendet. Ein Trap auf ERR, falls gesetzt, wird ausgeführt, bevor die Shell beendet wird.

Berücksichtigen Sie all dies, wenn Sie:

set -e
! command1
command2

Sie command1 das command1 set -e in command1 . Warum?

  • Wenn command1 ordnungsgemäß ausgeführt wird, wird der Status Null zurückgegeben. ! negiert es, aber set -e löst keinen Exit durch das aus, weil es aus einem mit! invertierten Rückgabestatus stammt, wie oben beschrieben.
  • Wenn command1 fehlschlägt, wird ein Status ungleich Null zurückgegeben. ! wird es negieren, so dass die Zeile am Ende einen Nullstatus zurückgibt und das Skript normal fortgesetzt wird.




sh