Jangan berhenti membuat jika perintah gagal, tetapi periksa status keluar

22

Saya mencoba untuk menginstruksikan GNU Make 3.81 untuk tidak berhenti jika suatu perintah gagal (jadi saya awali perintah dengan -) tetapi saya juga ingin memeriksa status keluar pada perintah berikutnya dan mencetak pesan yang lebih informatif. Namun Makefile saya di bawah gagal:

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

Mengapa Makefile di atas bergema "sukses!" bukannya "gagal!" ?

memperbarui:

Mengikuti dan memperluas jawaban yang diterima, di bawah ini adalah bagaimana seharusnya ditulis:

failure:                                                                                                                                                                                                                                      
    @-/bin/false && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"                                                                                                                                                                 
success:                                                                                                                                                                                                                                      
    @-/bin/true && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"     
Marcus Junius Brutus
sumber
2
Anda mungkin ingin menyelidiki .ONESHELL:arahan.
Jonathan Leffler
.ONESHELL akan menjalankan semua blok tanda terima dalam satu shell yang memiliki efek: jika perintah pertama gagal, yang berikutnya akan dieksekusi tanpa masalah. Untuk mencegah hal ini .SHELLFLAGS = -ecsebaiknya digunakan. Tetapi dalam hal ini Anda tidak dapat menggunakan -awalan lebih (untuk perintah tanda terima pribadi) karena make akan menulis bahwa kesalahan diabaikan tetapi masih akan gagal semua blok. Jadi, || :merupakan salah satu solusi untuk mengabaikan perintah. Tapi itu bukan cross-platform (Windows belum || :atau || true)
Paul-AG

Jawaban:

14

Setiap perintah pembaruan dalam aturan Makefile dieksekusi di shell terpisah. Jadi $? tidak mengandung status keluar dari perintah gagal sebelumnya, itu berisi apa pun nilai defaultnya adalah $? di shell baru. Itu sebabnya [$? -eq 0] Tes selalu berhasil.

Kyle Jones
sumber
10

Anda tidak perlu pengujian $?sejak &&berhasil jika $?nol dan ||diproses jika nilai pengembalian tidak nol.

Dan Anda tidak perlu minus karena nilai pengembalian untuk membuat diambil dari panggilan program proses terakhir dari saluran. Jadi ini berfungsi dengan baik

kegagalan:

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

keberhasilan:

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

Sebaliknya yang terjadi: Jika Anda ingin melakukan pesan Anda sendiri dan tetap ingin menghentikan proses make dengan nilai yang tidak nol, Anda perlu menulis sesuatu seperti ini:

kegagalan:

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

Dari GNU, buat dokumentasi :

Ketika kesalahan harus diabaikan, karena salah satu tanda '-' atau bendera '-i', buat suguhkan pengembalian kesalahan seperti halnya keberhasilan , kecuali bahwa ia mencetak pesan yang memberi tahu Anda kode status tempat shell keluar, dan mengatakan bahwa kesalahan telah diabaikan.

Untuk memanfaatkan makestatus keluar dalam kasus seperti ini, jalankan makedari skrip:

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

Dan siapkan Makefile Anda:

all:
    /bin/false
Timothy Martin
sumber