จับรหัสทางออกของคำสั่ง exit


10

ฉันมีสิ่งนี้ในสคริปต์ทุบตี:

exit 3;

exit_code="$?"

if [[ "$exit_code" != "0" ]]; then
    echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}";
    exit "$exit_code";
fi

ดูเหมือนว่าจะออกทันทีหลังจากคำสั่ง exit ซึ่งทำให้รู้สึก ฉันสงสัยว่าจะมีคำสั่งง่ายๆที่สามารถให้รหัสออกโดยไม่ต้องออกทันทีหรือไม่

ฉันจะเดา:

exec exit 3

exec: exit: not foundแต่จะให้ข้อความแสดงข้อผิดพลาด: ฉันควรทำอย่างไร :)


1
ใช่exec exit 3ไม่ใช่ bueno ฉันได้รับ"exec: exit: not found"

7
ฉันไม่เข้าใจคำถาม ทำไมไม่ตั้งค่าexit_code=3และกำจัดexit 3เส้นทั้งหมด?
wjandrea

@wjandrea เป็นคำถามเชิงแนวคิดมากกว่าเชิงปฏิบัติ

2
มันก็ไม่สมเหตุสมผลสำหรับฉัน ทำไมถึงมีรหัสการออกหากคุณไม่ได้ออกจากระบบจริง?
Barmar

1
@Barmar ทุกขั้นตอนมีรหัสทางออก คนส่วนใหญ่ที่พยายามตอบคำถามกำลังตีความคำถามเพื่อหมายถึง "ฉันจะแทนที่ 'exit 3' ด้วยสคริปต์ได้อย่างไรเพื่อให้ตั้งค่า$?ตัวแปร แต่ไม่ออกจากสคริปต์นี้ "
รัส

คำตอบ:


32

หากคุณมีสคริปต์ที่รันบางโปรแกรมและดูสถานะการออกของโปรแกรม (ด้วย  $?) และคุณต้องการทดสอบสคริปต์นั้นโดยทำสิ่ง ที่ทำให้$?การตั้งค่าเป็นค่าที่ทราบ (เช่น  3) เพียงแค่ทำ

(exit 3)

วงเล็บสร้างเชลล์ย่อย จากนั้นexitคำสั่งจะทำให้เชลล์ย่อยออกจากสถานะการออกที่ระบุ


นอกจากนี้เพื่อจุดประสงค์ในการดีบั๊กมันง่ายเหมือนการตั้งค่าexit_code="3"สำหรับการทดสอบ
Centimane


12

exitเป็น bash ในตัวดังนั้นคุณทำไม่execได้ ต่อคู่มือทุบตี :

สถานะการออกของ Bash คือสถานะการออกของคำสั่งสุดท้ายที่ดำเนินการในสคริปต์ หากไม่มีการดำเนินการคำสั่งสถานะการออกคือ 0

เมื่อรวมทั้งหมดนี้เข้าด้วยกันฉันจะบอกว่าตัวเลือกเดียวของคุณคือจัดเก็บสถานะทางออกที่คุณต้องการในตัวแปรแล้วexit $MY_EXIT_STATUSตามความเหมาะสม


hmmm คุณคิดอย่างไรเกี่ยวกับความคิดของ @G-man?

2
บางทีฉันอาจเข้าใจผิดว่าคุณกำลังพยายามทำให้สำเร็จ หากคุณเพียงแค่พยายามที่จะตั้งค่า$?(แม้ว่าฉันจะไม่แน่ใจว่าทำไมคุณจริง ๆ ) ที่ดูเหมือนคำตอบที่มั่นคง หากคุณต้องการตั้งค่าเป็นค่าที่ไม่ประสบความสำเร็จfalseเป็นอีกตัวเลือกหนึ่ง
solarshado

10

คุณสามารถเขียนฟังก์ชันที่คืนค่าสถานะที่กำหนดเป็นอาร์กิวเมนต์หรือ255ถ้าไม่มีให้ (ฉันเรียกมันretว่า "คืน" ค่าของมัน)

ret() { return "${1:-255}"; }

และใช้ในสถานที่ของการเรียกร้องให้ret exitนี่เป็นการหลีกเลี่ยงความไร้ประสิทธิภาพของการสร้างเชลล์ย่อยในคำตอบที่ยอมรับในปัจจุบัน

วัดบ้าง

time bash -c 'for i in {1..10000} ; do (exit 3) ; done ; echo $?'

บนเครื่องของฉันใช้เวลาประมาณ 3.5 วินาที

 time bash -c 'ret(){ return $1 ; } ; for i in {1..10000} ; do ret 3 ; done ; echo $?'

บนเครื่องของฉันใช้เวลาประมาณ 0.051 วินาทีเร็วกว่า 70 เท่า การใส่ค่าเริ่มต้นจะทำให้เร็วขึ้น 60 เท่า เห็นได้ชัดว่าห่วงมีค่าใช้จ่าย ถ้าฉันเปลี่ยนเนื้อความของลูปเป็นเพียง:หรือtrueจากนั้นเวลาจะลดลงครึ่งหนึ่งเป็น 0.025 ลูปที่ว่างเปล่าโดยสิ้นเชิงคือไวยากรณ์ที่ไม่ถูกต้อง การเพิ่ม;:ไปยังลูปแสดงให้เห็นว่าคำสั่งขั้นต่ำนี้ใช้เวลา 0.007 วินาทีดังนั้นค่าใช้จ่ายในลูปจะอยู่ที่ประมาณ 0.018 การลบค่าใช้จ่ายนี้จากการทดสอบสองครั้งแสดงให้เห็นว่าการretแก้ปัญหานั้นเร็วกว่า 100 เท่า

เห็นได้ชัดว่านี่คือการวัดสังเคราะห์ แต่สิ่งต่าง ๆ เพิ่มขึ้น หากคุณทำทุกอย่างช้ากว่าที่พวกเขาต้องการ 100 เท่าคุณจะต้องจบด้วยระบบช้า 0.0


2
@iBug ไม่ต้องการพื้นที่เพิ่มเติม
รัส

ข้อดีของการสร้าง sub-shell ฉันได้อ่านแล้วว่ากระสุนบางอันอาจฉลาดพอที่จะแยกทางแยกในกรณีเช่นนี้ แต่การทุบตีนั้นไม่ใช่หนึ่งในนั้น
G-Man กล่าวว่า 'Reinstate Monica'

3

เกี่ยวกับexec exit 3... มันจะพยายามเรียกใช้คำสั่งภายนอกที่เรียกว่าexitแต่ไม่มีคำสั่งดังนั้นคุณจะได้รับข้อผิดพลาด มันจะต้องเป็นคำสั่งภายนอกแทนที่จะเป็นหนึ่งในตัวเชลล์เนื่องจากexec แทนที่เชลล์อย่างสมบูรณ์ ซึ่งก็หมายความว่าแม้ว่าคุณจะมีคำสั่งภายนอกเรียกว่าexit, exec exit 3จะไม่กลับไปดำเนินการต่อเชลล์สคริปต์ของคุณเนื่องจากเปลือกจะไม่มีผู้ใดเพิ่มเติม


1
ผมคิดว่าคุณสามารถทำแต่ในขณะที่ฉันไม่สามารถคิดเหตุผลที่จะทำที่ใดเมื่อเทียบกับเพียงexec bash -c "exit 3" exit 3
David Z

1
@DavidZ ไม่ว่าในกรณีใดการexec'ing หรือเพียงexit' ing จะหยุดสคริปต์ซึ่งดูเหมือนจะไม่เหมือนที่คำถามต้องการ
ilkkachu

3

คุณสามารถทำได้ด้วย Awk:

awk 'BEGIN{exit 9}'

หรือ Sed:

sed Q9 /proc/stat

... หรือกับกระสุน:sh -c 'exit 9'
ilkkachu

1
@ilkkachu ถ้าคุณกำลังจะทำเช่นนั้นคุณอาจทำ(exit 9)คำตอบที่ได้รับการยอมรับ
Steven Penny
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.