อย่าหยุดทำการสร้างหากคำสั่งล้มเหลว แต่ตรวจสอบสถานะออก


22

ฉันกำลังพยายามสั่ง GNU ทำให้ 3.81 ไม่หยุดถ้าคำสั่งล้มเหลว (ดังนั้นฉันจึงนำหน้าคำสั่งด้วย-) แต่ฉันต้องการตรวจสอบสถานะการออกจากคำสั่งถัดไปและพิมพ์ข้อความที่ให้ข้อมูลเพิ่มเติม อย่างไรก็ตาม Makefile ของฉันด้านล่างล้มเหลว:

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

เหตุใด Makefile ด้านบนจึงแสดงว่า "สำเร็จ!" แทนที่จะเป็น "ความล้มเหลว!" ?

อัปเดต:

การติดตามและขยายคำตอบที่ได้รับการยอมรับด้านล่างเป็นวิธีการเขียน:

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

2
คุณอาจต้องการตรวจสอบ.ONESHELL:คำสั่ง
Jonathan Leffler

. ONESHELL จะเรียกใช้บล็อกการรับสินค้าทั้งหมดในเชลล์เดียวซึ่งมีผลกระทบ: หากคำสั่งแรกล้มเหลวจะมีการรันคำสั่งถัดไปโดยไม่มีปัญหา เพื่อป้องกันสิ่งนี้.SHELLFLAGS = -ecควรใช้ แต่ในกรณีนี้คุณไม่สามารถใช้-คำนำหน้าเพิ่มเติมได้ (สำหรับคำสั่งส่วนตัวของใบเสร็จ) เพราะการทำจะเขียนข้อผิดพลาดนั้นจะถูกละเว้น แต่ก็จะยังคงบล็อกทั้งหมดล้มเหลว ดังนั้น|| :เป็นหนึ่งในวิธีการแก้คำสั่งที่จะไม่สนใจ แต่มันไม่ใช่ข้ามแพลตฟอร์ม (Windows มี|| :หรือไม่|| true)
Paul-AG

คำตอบ:


14

คำสั่งอัพเดตแต่ละคำสั่งในกฎ Makefile จะถูกดำเนินการในเชลล์แยกต่างหาก ดังนั้น $ ไม่ได้มีสถานะการออกของคำสั่งที่ล้มเหลวก่อนหน้านี้มันมีสิ่งใดที่ค่าเริ่มต้นสำหรับ $? ในเปลือกใหม่ นั่นคือเหตุผลที่คุณ [$? -eq 0] การทดสอบสำเร็จเสมอ


10

คุณไม่จำเป็นต้องมีการทดสอบ$?ตั้งแต่&&ทำงานถ้า$?เป็นศูนย์และ||จะดำเนินการในกรณีที่มีค่าตอบแทนที่ไม่เป็นศูนย์

และคุณไม่ต้องการลบด้วยค่าที่ส่งคืนจากการเรียกใช้โปรแกรมล่าสุดของบรรทัด ดังนั้นจึงใช้งานได้ดี

ความล้มเหลว:

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

ความสำเร็จ:

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

ตรงข้ามเกิดขึ้น: หากคุณต้องการทำข้อความของคุณเองและต้องการที่จะทำลายกระบวนการสร้างด้วยค่าที่ไม่เป็นศูนย์คุณต้องเขียนสิ่งนี้:

ความล้มเหลว:

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

8

จากGNU ทำเอกสาร :

เมื่อต้องละเว้นข้อผิดพลาดเนื่องจากการตั้งค่าสถานะ '-' หรือ '-i' ให้ดำเนินการข้อผิดพลาดกลับเหมือนกับความสำเร็จยกเว้นว่ามันพิมพ์ข้อความที่บอกรหัสสถานะที่เชลล์ออกด้วยและ ระบุว่าข้อผิดพลาดถูกละเว้น

หากต้องการใช้makeสถานะการออกของในกรณีเช่นนี้ให้เรียกใช้งานmakeจากสคริปต์:

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

และให้ Makefile ของคุณประกอบด้วย:

all:
    /bin/false
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.