Non smettere di fare se un comando fallisce, ma controlla lo stato di uscita


22

Sto cercando di indicare a GNU Make 3.81 di non fermarsi se un comando fallisce (quindi prefisso il comando con -) ma voglio anche controllare lo stato di uscita sul comando successivo e stampare un messaggio più informativo. Tuttavia il mio Makefile qui sotto fallisce:

$ 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!

Perché il Makefile sopra fa eco "successo!" invece di "fallimento!" ?

aggiornare:

Di seguito e l'espansione della risposta accettata, di seguito è riportato come deve essere scritto:

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

2
Potresti voler indagare sulla .ONESHELL:direttiva.
Jonathan Leffler,

.ONESHELL eseguirà tutti i blocchi di ricevute in una shell che ha effetto: se il primo comando fallisce, quelli successivi verranno eseguiti senza problemi. Per evitare questo .SHELLFLAGS = -ecdovrebbe essere usato. Ma in questo caso non è possibile utilizzare -più il prefisso (per il comando personale della ricevuta) perché il make scriverà che l'errore viene ignorato ma comunque fallirà tutto il blocco. Quindi, || :è una soluzione per ignorare il comando. Ma non è multipiattaforma (Windows no || :o || true)
Paul-AG,

Risposte:


14

Ogni comando di aggiornamento in una regola Makefile viene eseguito in una shell separata. Quindi $? non contiene lo stato di uscita del precedente comando non riuscito, contiene qualunque sia il valore predefinito per $? in una nuova shell. Ecco perché il tuo [$? -eq 0] il test ha sempre esito positivo.


10

Non è necessario il test di $?poiché &&funziona se $?è zero e ||procede in caso di un valore di ritorno diverso da zero.

E non è necessario il segno negativo poiché al valore di ritorno da effettuare viene preso dall'ultima chiamata al programma procedi della linea. Quindi funziona bene

fallimento:

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

successo:

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

Succede il contrario: se vuoi scrivere il tuo messaggio e vuoi interrompere comunque il processo di creazione con un valore diverso da zero, devi scrivere qualcosa del genere:

fallimento:

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

8

Dalla GNU fare la documentazione :

Quando gli errori devono essere ignorati, a causa di un flag '-' o '-i', fare in modo che gli ossequi restituiscano un errore esattamente come successo , tranne per il fatto che stampa un messaggio che ti dice il codice di stato con cui la shell è uscita, e dice che l'errore è stato ignorato.

Per utilizzare lo makestato di uscita in un caso come questo, eseguire makeda uno script:

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

E fai in modo che il tuo Makefile contenga:

all:
    /bin/false
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.