Đừng dừng thực hiện nếu một lệnh thất bại, nhưng kiểm tra trạng thái thoát


22

Tôi đang cố gắng hướng dẫn GNU Make 3.81 không dừng lại nếu một lệnh thất bại (vì vậy tôi đặt tiền tố cho lệnh -) nhưng tôi cũng muốn kiểm tra trạng thái thoát trên lệnh tiếp theo và in một thông báo nhiều thông tin hơn. Tuy nhiên Makefile của tôi dưới đây không thành công:

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

Tại sao Makefile ở trên echo "thành công!" thay vì "thất bại!" ?

cập nhật:

Theo dõi và mở rộng câu trả lời được chấp nhận, dưới đây là cách viết:

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

2
Bạn có thể muốn điều tra .ONESHELL:chỉ thị.
Jonathan Leffler

.ONESHELL sẽ chạy tất cả các khối biên nhận trong một shell có hiệu lực: nếu lệnh đầu tiên thất bại, các khối tiếp theo sẽ được thực thi mà không gặp vấn đề gì. Để ngăn chặn điều này .SHELLFLAGS = -ecnên được sử dụng. Nhưng trong trường hợp này, bạn không thể sử dụng -tiền tố nhiều hơn (đối với lệnh cá nhân của biên nhận) vì make sẽ ghi lỗi đó bị bỏ qua nhưng vẫn sẽ thất bại trong tất cả các khối. Vì vậy, || :là một trong những giải pháp để bỏ qua lệnh. Nhưng đó không phải là đa nền tảng (Windows chưa || :hoặc || true)
Paul-AG

Câu trả lời:


14

Mỗi lệnh cập nhật trong quy tắc Makefile được thực thi trong một shell riêng. Vậy $? không chứa trạng thái thoát của lệnh thất bại trước đó, nó chứa bất cứ giá trị mặc định nào cho $? trong một vỏ mới. Đó là lý do tại sao [$ của bạn? -eq 0] kiểm tra luôn thành công.


10

Bạn không cần kiểm tra $?kể từ khi &&hoạt động nếu $?bằng 0 và ||được tiến hành trong trường hợp giá trị trả về khác không.

Và bạn không cần trừ vì giá trị trả về được thực hiện từ cuộc gọi chương trình tiếp theo cuối cùng của dòng. Vì vậy, điều này làm việc tốt

thất bại:

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

sự thành công:

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

Điều ngược lại xảy ra: Nếu bạn muốn thực hiện thông điệp của riêng mình và muốn phá vỡ quy trình thực hiện bằng bất kỳ giá trị khác không, bạn cần phải viết một cái gì đó như thế này:

thất bại:

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

8

Từ GNU tạo tài liệu :

Khi lỗi được bỏ qua, vì cờ '-' hoặc cờ '-i', hãy xử lý trả về lỗi giống như thành công , ngoại trừ việc nó in ra một thông báo cho bạn biết mã trạng thái mà trình bao thoát ra và nói rằng lỗi đã bị bỏ qua.

Để sử dụng maketrạng thái thoát trong trường hợp như thế này, hãy thực thi maketừ tập lệnh:

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

Và có Makefile của bạn chứa:

all:
    /bin/false
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.