Hören Sie nicht auf zu machen, wenn ein Befehl fehlschlägt, sondern überprüfen Sie den Beendigungsstatus


22

Ich versuche, GNU Make 3.81 anzuweisen, nicht anzuhalten, wenn ein Befehl fehlschlägt (daher stelle ich dem Befehl das Präfix voran -), aber ich möchte auch den Beendigungsstatus beim nächsten Befehl überprüfen und eine informativere Meldung ausgeben. Mein unten stehendes Makefile schlägt jedoch fehl:

$ cat Makefile 
all:
    -/bin/false
    ([ $$? -eq 0 ] && echo "success!") || echo "failure!"
$
$ make
/bin/false
make: [all] Error 1 (ignored)
([ $? -eq 0 ] && echo "success!") || echo "failure!"
success!

Warum echo das Makefile oben "Erfolg!" statt "scheitern!" ?

aktualisieren:

Im Folgenden wird die akzeptierte Antwort beschrieben und erweitert:

failure:                                                                                                                                                                                                                                      
    @-/bin/false && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"                                                                                                                                                                 
success:                                                                                                                                                                                                                                      
    @-/bin/true && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"     

2
Möglicherweise möchten Sie die .ONESHELL:Richtlinie untersuchen.
Jonathan Leffler

.ONESHELL führt alle Empfangsblöcke in einer Shell aus, was sich auswirkt: Wenn der erste Befehl fehlschlägt, werden die nächsten ohne Probleme ausgeführt. Um dies zu verhindern, .SHELLFLAGS = -ecsollte verwendet werden. In diesem Fall können Sie jedoch nicht -mehr das Präfix (für den persönlichen Befehl der Quittung) verwenden, da das make schreibt, dass der Fehler ignoriert wird, aber trotzdem den gesamten Block nicht besteht. Ist || :also eine Lösung, um den Befehl zu ignorieren. Aber es ist nicht plattformübergreifend (Windows hat nicht || :oder || true)
Paul-AG

Antworten:


14

Jeder Aktualisierungsbefehl in einer Makefile-Regel wird in einer separaten Shell ausgeführt. Also $? enthält nicht den Exit-Status des vorherigen fehlgeschlagenen Befehls, sondern den Standardwert für $? in einer neuen Schale. Deshalb sind deine [$? -eq 0] test ist immer erfolgreich.


10

Der Test von $?since &&funktioniert nicht, wenn $?Null ||ist, und wird bei einem Rückgabewert ungleich Null fortgesetzt.

Und Sie brauchen das Minus nicht zu machen, da der Rückgabewert aus dem letzten Fortsetzungsprogrammaufruf der Zeile übernommen wird. Das funktioniert also gut

Fehler:

      @/bin/false && echo "success!" || echo "failure!" 

Erfolg:

      @/bin/true && echo "success!" || echo "failure!"

Das Gegenteil ist der Fall: Wenn Sie Ihre eigene Nachricht verfassen und den Erstellungsprozess trotzdem mit einem Wert ungleich Null unterbrechen möchten, müssen Sie Folgendes schreiben:

Fehler:

      @/bin/false && echo "success!" || { echo "failure!"; exit 1; }

8

Aus der GNU make Dokumentation :

Wenn Fehler aufgrund eines '-' oder des '-i'-Flags ignoriert werden sollen, wird eine Fehlerrückgabe genauso wie ein Erfolg behandelt , mit der Ausnahme, dass eine Meldung ausgegeben wird, in der der Statuscode angegeben ist, mit dem die Shell beendet wurde, und sagt, dass der Fehler ignoriert wurde.

Um makein einem solchen Fall den Exit-Status von zu verwenden, führen Sie Folgendes makeaus:

#!/bin/bash
make
([ $? -eq 0 ] && echo "success!") || echo "failure!"

Und lassen Sie Ihr Makefile enthalten:

all:
    /bin/false
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.