การใช้รหัส“ สงวน” สำหรับสถานะการออกของเชลล์สคริปต์


15

ฉันเพิ่งเจอรายการรหัสทางออกนี้ด้วยความหมายพิเศษจากคู่มือการใช้สคริปต์การทุบตีขั้นสูง พวกเขาอ้างถึงรหัสเหล่านี้เป็นการสงวนและแนะนำว่า:

ตามตารางด้านบนรหัสทางออก 1-2, 126-165 และ 255 มีความหมายพิเศษและควรหลีกเลี่ยงสำหรับพารามิเตอร์ทางออกที่ผู้ใช้ระบุ

ไม่นานมานี้ฉันเขียนสคริปต์ซึ่งใช้รหัสสถานะการออกต่อไปนี้:

  • 0 - สำเร็จ
  • 1 - ชื่อโฮสต์ไม่ถูกต้อง
  • 2 - ระบุอาร์กิวเมนต์ที่ไม่ถูกต้อง
  • 3 - สิทธิ์ผู้ใช้ไม่เพียงพอ

เมื่อฉันเขียนสคริปต์ฉันไม่ทราบรหัสทางออกพิเศษดังนั้นฉันจึงเริ่มต้นที่ 1 สำหรับเงื่อนไขข้อผิดพลาดแรกและเพิ่มสถานะทางออกสำหรับแต่ละประเภทข้อผิดพลาดต่อเนื่อง

ฉันเขียนสคริปต์ด้วยความตั้งใจว่าในเวลาต่อมาสคริปต์อื่น ๆ สามารถเรียกใช้ได้ (ซึ่งสามารถตรวจสอบรหัสทางออกที่ไม่เป็นศูนย์) ฉันยังไม่ได้ทำอย่างนั้นจริง ๆ ; จนถึงตอนนี้ฉันแค่เรียกใช้สคริปต์จากเชลล์เชิงโต้ตอบของฉัน (Bash) และฉันสงสัยว่าจะเกิดอะไรขึ้นหากใช้รหัสทางออกที่กำหนดเอง คำแนะนำจากคู่มือ Bash-Scripting ขั้นสูงมีความเกี่ยวข้อง / สำคัญเพียงใด

ฉันไม่พบคำแนะนำการยืนยันใด ๆ ในเอกสาร Bash; ส่วนของมันที่สถานะการออกเพียงแค่แสดงรหัสทางออกที่ใช้โดย Bash แต่ไม่ได้ระบุว่าสิ่งเหล่านี้สงวนไว้หรือเตือนให้ใช้สำหรับสคริปต์ / โปรแกรมของคุณเอง


6
ฉันและคนอื่น ๆ พิจารณาว่า ABSG นั้นมีคุณภาพต่ำโดยทั่วไป ในความเห็นของฉันผู้เขียนหน้าเว็บที่คุณเชื่อมโยงนั้นยืนยันว่ารหัสทางออกที่ระบุไว้นั้นไม่ได้รับการสนับสนุนตามความจริงที่ว่าตัวเชลล์ใช้สำหรับความหมายเฉพาะ มีความพยายามในการสร้างมาตรฐานสำหรับสคริปต์ซึ่งไม่ประสบความสำเร็จ สิ่งสำคัญคือการจัดทำเอกสารรหัสข้อผิดพลาดที่คุณเลือกเพื่อให้ผู้บริโภคในสคริปต์ของคุณ (เช่นสคริปต์อื่น ๆ ) รู้ว่าต้องทำอย่างไร
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

@DennisWilliamson ถ้าคุณโพสต์ความคิดเห็นของคุณเป็นคำตอบฉันมีความสุขที่จะโหวตมัน; ฉันโหวตให้คำตอบอื่น ๆ ทั้งหมดแล้วเมื่อพบว่าคำตอบเหล่านั้นมีประโยชน์ ในขณะที่คำตอบของคุณคล้ายกับเนื้อหาของ David King (และในระดับที่น้อยกว่าของ Zwol) คุณระบุอย่างชัดเจนว่าไม่มีหลักฐานการยืนยันในใบเสนอราคา ABSG
Anthony G - ความยุติธรรมสำหรับโมนิก้า

1
ขอบคุณสำหรับข้อเสนอ แต่ฉันเชื่อว่าความคิดเห็นของฉันควรอยู่เช่นนี้
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

ตั้งแต่ฉันค้นพบว่าข้อมูลจำเพาะ POSIX มีคำแนะนำที่คล้ายกันดังนั้นฉันจึงเพิ่มข้อมูลนั้นลงในคำตอบของฉันเอง (มีผลการวิจัยตั้งแต่ถามคำถามนี้)
Anthony G - ความยุติธรรมสำหรับโมนิก้า

คำตอบ:


10

มีความพยายามหลายครั้งในการสร้างมาตรฐานความหมายของรหัสออกจากกระบวนการ นอกจากสิ่งที่คุณพูดถึงฉันรู้ว่า:

  • BSD มีการsysexits.hกำหนดความหมายของค่าตั้งแต่ 64 ขึ้นไป

  • grepเอกสารGNU ที่รหัสทางออก 0 หมายถึงพบการแข่งขันอย่างน้อยหนึ่งรายการ 1 หมายถึงไม่พบการแข่งขันและ 2 หมายถึงข้อผิดพลาด I / O เกิดขึ้น เห็นได้ชัดว่าการประชุมนี้มีประโยชน์สำหรับโปรแกรมอื่น ๆ ซึ่งความแตกต่างระหว่าง "ไม่มีอะไรผิดพลาด แต่ฉันไม่พบอะไรเลย" และ "ข้อผิดพลาด I / O ที่เกิดขึ้น" มีความหมาย

  • การใช้งานหลายอย่างของฟังก์ชั่นไลบรารี C systemใช้รหัสออก 127 เพื่อระบุว่าโปรแกรมไม่มีอยู่หรือไม่สามารถเริ่มต้นได้

  • ใน Windows NTSTATUSรหัส (ซึ่งกระจัดกระจายไปทั่วพื้นที่หมายเลข 32- บิต) โดยไม่สะดวกอาจถูกใช้เป็นรหัสทางออกโดยเฉพาะอย่างยิ่งรหัสที่ระบุกระบวนการที่ถูกยกเลิกเนื่องจากการกระทำที่ไม่เหมาะสมอย่างหายนะ (เช่นSTATUS_STACK_OVERFLOW)

คุณไม่สามารถเชื่อใจได้ว่าโปรแกรมใดก็ตามที่ปฏิบัติตามอนุสัญญาเหล่านี้โดยเฉพาะ กฎที่เชื่อถือได้เพียงอย่างเดียวคือรหัสทางออก 0 คือความสำเร็จและสิ่งอื่น ๆ ก็คือความล้มเหลวบางประเภท (หมายเหตุว่า C89 ของEXIT_SUCCESSถูกไม่ได้รับประกันว่าจะมีค่าเป็นศูนย์ แต่exit(0)จะต้องประพฤติตัวเหมือนกันกับexit(EXIT_SUCCESS). แม้ว่าค่าจะไม่เหมือนกัน)


ขอบคุณ เป็นการยากที่จะเลือกคำตอบเดียวมากกว่าคำตอบอื่น ๆ แต่ฉันยอมรับคำตอบนี้เนื่องจากตอบคำถามของฉันในขณะเดียวกันก็ให้รหัสทางออกที่แตกต่างกันในการใช้งาน (พร้อมลิงก์ที่เกี่ยวข้อง): มันสมควรได้รับมากกว่า 3 upvotes ปัจจุบันมี
Anthony G - ความยุติธรรมสำหรับโมนิก้า

11

ไม่มีรหัสการออกมีความหมายพิเศษ แต่ค่าใน$?อาจมีความหมายพิเศษ

วิธีที่ Bourne Shell และ ksh93 จัดการและส่งต่อโค้ดทางออกและสถานการณ์ข้อผิดพลาดให้กับตัวแปรเชลล์$?คือปัญหา ตรงกันข้ามกับสิ่งที่คุณลิสต์มีเพียงค่าต่อไปนี้ที่$?มีความหมายพิเศษ:

  • 126 ไม่สามารถดำเนินการไบนารีได้แม้ว่าจะมีอยู่ก็ตาม
  • 127 ไบนารีที่ระบุไม่มีอยู่
  • สถานะทางออก 128 คือ == 0 แต่มีปัญหาบางอย่างที่ไม่ได้ระบุ

นอกจากนี้ยังมีเชลล์ที่ไม่ระบุและช่วง$?รหัสเฉพาะแพลตฟอร์ม> 128 ที่สงวนไว้สำหรับโปรแกรมที่ถูกขัดจังหวะด้วยสัญญาณ:

  • Bourne Shell bash และ ksh88 ใช้หมายเลขสัญญาณ 128 +
  • ksh93 ใช้หมายเลขสัญญาณ 256 +

ค่าอื่นไม่ให้ปัญหาเนื่องจากอาจแตกต่างจาก$?ค่าพิเศษของเชลล์

โดยเฉพาะอย่างยิ่งค่า 1 และ 2 ไม่ได้ใช้สำหรับเงื่อนไขพิเศษ แต่เป็นเพียงรหัสทางออกที่ใช้โดยคำสั่ง builtin ที่สามารถทำหน้าที่เหมือนกันได้เมื่อไม่มีบิลด์ ดังนั้นดูเหมือนว่าตัวชี้ไปยังคู่มือสคริปต์การทุบตีที่คุณให้มานั้นไม่ใช่คู่มือที่ดีเพราะมันแสดงรายการรหัสที่ใช้โดยการทุบตีโดยไม่ต้องแสดงความคิดเห็นว่ารหัสเฉพาะเป็นค่าพิเศษที่ควรหลีกเลี่ยงสำหรับสคริปต์ของตัวเอง

Bourne Shell เวอร์ชันใหม่ใช้waitid()แทนwaitpid()การรอให้โปรแกรมออกและwaitid()(แนะนำ 1989 สำหรับ SVr4) ใช้อินเตอร์เฟส syscall ที่ดีกว่า (คล้ายกับที่ใช้ใน UNOS ในปี 1980)

เนื่องจากบอร์นเชลล์รุ่นใหม่เข้ารหัสเหตุผลการออกในตัวแปรแยก${.sh.code}/ ${.sh.codename}กว่ารหัสออกที่อยู่ใน${.sh.status}/ ${.sh.termsig}ดูhttp://schillix.sourceforge.net/man/man1/bosh.1.htmlรหัสทางออกไม่ได้รับการโหลดมากเกินไป ด้วยสถานะพิเศษและจากการใช้ `waitid () Bourne Shell จะรองรับการส่งคืนรหัสทางออก 32 บิตทั้งหมดไม่ใช่แค่บิตต่ำ 8 บิต

BTW: ระวังอย่าให้exit(256)คล้ายหรือคล้ายกับ C-program หรือ shell script เนื่องจากผลลัพธ์นี้$?ถูกตีความว่าเป็น 0 ในเชลล์คลาสสิก


2
BTW: ฉันทำรายงานข้อผิดพลาดกับ FreeBSD และเคอร์เนล Linux สำหรับwaitid()ข้อผิดพลาดนี้ประมาณปลายเดือนพฤษภาคม คน FreeBSD แก้ไขปัญหาภายใน 20 ชั่วโมงคน Linux ไม่สนใจแก้ไขบั๊ก ... และผู้คนใน Cygwin บอกว่าพวกเขามีข้อผิดพลาดจากข้อผิดพลาดที่เข้ากันได้กับ Linux ;-)
Schily

2
ลักษณะการทำงานนี้จำเป็นต้องใช้กับข้อมูลจำเพาะ Unix เดี่ยว มีค่า 32 บิตใช่ แต่ค่าที่มี bitfield 8 บิตที่มีต่ำ 8 _exitบิตของค่าจาก โปรดเชื่อมโยงรายงานข้อผิดพลาด FreeBSD ที่คุณอ้างถึงบางทีฉันอาจเข้าใจผิดถึงปัญหาที่คุณอธิบาย
Random832

2
OP ติดแท็กคำถามด้วยbashและกล่าวถึง Bash ในเนื้อหาของคำถาม Bash เป็นเปลือกที่ได้มาจากบอร์น มันไม่รองรับ${.sh.}ตัวแปร อย่างไรก็ตามเป็นเรื่องจริงที่คุณพูดว่า "Bourne" และไม่ใช่ "Bourne-ได้รับ" (แม้ว่าคุณจะรวม ksh93)
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

2
คำตอบนี้ดูเหมือนจะเฉพาะเจาะจงมากสำหรับรุ่น Unix ที่ได้มาจาก SVR4 โปรดชัดเจนเกี่ยวกับสิ่งที่พกพาได้และสิ่งที่ไม่จำไว้ว่าไม่มีสิ่งเช่น "Bourne shell" เว้นแต่คุณจะหมายถึงสิ่งที่อยู่ใน V7
zwol

4
ในทางตรงกันข้ามฉันเชื่อว่าเป็นคุณที่เข้าใจช่วงของการเปลี่ยนแปลงที่นี่โดยเฉพาะอย่างยิ่งการเปลี่ยนแปลงทางประวัติศาสตร์ คุณทำให้ดูเหมือนว่า/bin/shสามารถพึ่งพาเพื่อประพฤติ wrt รหัสทางออกพิเศษเหล่านี้ข้ามแพลตฟอร์มซึ่งไม่เป็นความจริง (ฉันไม่สนใจว่าระบบใด ๆ/bin/shสามารถพูดได้ว่าเป็น "บอร์นเชลล์ตัวจริง" สำคัญกว่ามากที่จะรู้ว่าไม่มีสิ่งใดใน POSIX และสิ่งที่คุณอ้างถึงในฐานะ "ระบบ Unix จริง" ส่วนใหญ่ เสื้อให้ POSIX สอดคล้อง/bin/shอยู่แล้ว).
zwol

6

สำหรับการเขียนสคริปต์เชลล์ในบางครั้งฉันก็จะเทียบเท่าsysexist.hเชลล์ที่มีรหัสทางออกของเชลล์ที่สงวนไว้ (นำหน้าด้วยS_EX_) ซึ่งฉันตั้งชื่อไว้exit.sh

มันเป็นพื้น:

EX_OK=0 # successful termination 
EX__BASE=64     # base value for error messages 
EX_USAGE=64     # command line usage error 
EX_DATAERR=65   # data format error 
EX_NOINPUT=66   # cannot open input 
EX_NOUSER=67    # addressee unknown 
EX_NOHOST=68    # host name unknown 
EX_UNAVAILABLE=69       # service unavailable 
EX_SOFTWARE=70  # internal software error 
EX_OSERR=71     # system error (e.g., can't fork) 
EX_OSFILE=72    # critical OS file missing 
EX_CANTCREAT=73 # can't create (user) output file 
EX_IOERR=74     # input/output error 
EX_TEMPFAIL=75  # temp failure; user is invited to retry 
EX_PROTOCOL=76  # remote error in protocol 
EX_NOPERM=77    # permission denied 
EX_CONFIG=78    # configuration error 
EX__MAX=78      # maximum listed value 

#System errors
S_EX_ANY=1      #Catchall for general errors
S_EX_SH=2       #Misuse of shell builtins (according to Bash documentation); seldom seen
S_EX_EXEC=126   #Command invoked cannot execute         Permission problem or command is not an executable
S_EX_NOENT=127  #"command not found"    illegal_command Possible problem with $PATH or a typo
S_EX_INVAL=128  #Invalid argument to exit       exit 3.14159    exit takes only integer args in the range 0 - 255 (see first footnote)                                                                                        
#128+n  Fatal error signal "n"  kill -9 $PPID of script $? returns 137 (128 + 9)                               
#255*   Exit status out of range        exit -1 exit takes only integer args in the range 0 - 255              
S_EX_HUP=129                                                                                                   
S_EX_INT=130   
#...

และสามารถสร้างขึ้นด้วย:

#!/bin/sh
src=/usr/include/sysexits.h
echo "# Generated from \"$src\"" 
echo "# Please inspect the source file for more detailed descriptions"
echo
< "$src" sed -rn 's/^#define  *(\w+)\s*(\d*)/\1=\2/p'| sed 's:/\*:#:; s:\*/::'
cat<<'EOF'

#System errors
S_EX_ANY=1  #Catchall for general errors
S_EX_SH=2   #Misuse of shell builtins (according to Bash documentation); seldom seen
S_EX_EXEC=126   #Command invoked cannot execute     Permission problem or command is not an executable
S_EX_NOENT=127  #"command not found"    illegal_command Possible problem with $PATH or a typo
S_EX_INVAL=128  #Invalid argument to exit   exit 3.14159    exit takes only integer args in the range 0 - 255 (see first footnote)
#128+n  Fatal error signal "n"  kill -9 $PPID of script $? returns 137 (128 + 9)
#255*   Exit status out of range    exit -1 exit takes only integer args in the range 0 - 255
EOF
$(which kill) -l |tr ' ' '\n'| awk '{ printf "S_EX_%s=%s\n", $0, 128+NR; }'

ฉันไม่ได้ใช้มันมากนัก แต่สิ่งที่ฉันใช้ก็คือฟังก์ชั่นของเชลล์ที่ใช้รหัสข้อผิดพลาดในรูปแบบสตริง ฉันตั้งชื่อมันexit2strแล้ว สมมติว่าคุณตั้งชื่อดังกล่าวข้างต้นexit.shกำเนิดexit.sh.shรหัสสำหรับexit2strสามารถสร้างขึ้นด้วย ( exit2str.sh.sh):

#!/bin/sh
echo '
exit2str(){
  case "$1" in'
./exit.sh.sh | sed -nEe's|^(S_)?EX_(([^_=]+_?)+)=([0-9]+).*|\4) echo "\1\2";;|p'
echo "
  esac
}"

ฉันใช้สิ่งนี้ในส่วนPS1ของเชลล์เชิงโต้ตอบของฉันดังนั้นหลังจากที่แต่ละคำสั่งที่ฉันรันฉันสามารถเห็นสถานะการออกและรูปแบบสตริงของมัน (ถ้ามันมีรูปแบบสตริงที่รู้จัก):

[15:58] pjump@laptop:~ 
(0=OK)$ 
[15:59] pjump@laptop:~ 
(0=OK)$ fdsaf
fdsaf: command not found
[15:59] pjump@laptop:~ 
(127=S_NOENT)$ sleep
sleep: missing operand
Try 'sleep --help' for more information.
[15:59] pjump@laptop:~ 
(1=S_ANY)$ sleep 100
^C
[15:59] pjump@laptop:~ 
(130=S_INT)$ sleep 100
^Z
[1]+  Stopped                 sleep 100
[15:59] pjump@laptop:~ 
(148=S_TSTP)$

ในการรับสิ่งเหล่านี้คุณต้องมี insourcable สำหรับฟังก์ชัน exit2str:

$ ./exit2str.sh.sh > exit2str.sh #Place this somewhere in your PATH

จากนั้นใช้ใน~/.bashrcการบันทึกและแปลรหัสออกในแต่ละพรอมต์คำสั่งและแสดงพรอมต์ของคุณ ( PS1):

    # ...
    . exit2str.sh
PROMPT_COMMAND='lastStatus=$(st="$?"; echo -n "$st"; str=$(exit2str "$st") && echo "=$str"); # ...'
    PS1="$PS1"'\n($lastStatus)\$'
    # ...                                                                                   

มันค่อนข้างมีประโยชน์สำหรับการสังเกตว่าบางโปรแกรมปฏิบัติตามอนุสัญญารหัสออกและบางโปรแกรมไม่ใช้เพื่อเรียนรู้เกี่ยวกับระเบียบการออกรหัสหรือเพียงเพื่อให้สามารถเห็นสิ่งที่เกิดขึ้นได้ง่ายขึ้น หลังจากใช้มาระยะหนึ่งฉันสามารถพูดได้ว่าเชลล์สคริปต์ที่เน้นระบบจำนวนมากปฏิบัติตามอนุสัญญา EX_USAGEเป็นเรื่องธรรมดาโดยเฉพาะอย่างยิ่งแม้ว่ารหัสอื่น ๆ ไม่มาก ฉันพยายามติดตามการประชุมเป็นครั้งคราวถึงแม้ว่าจะมี$S_EX_ANY(1) สำหรับคนขี้เกียจ (ฉันเป็นคนเดียว)


ฉันสงสัยว่ามีอะไรที่เหมือนกับการทำแผนที่ระหว่างรหัส errno และรหัสออกเพื่อใช้ถ้าข้อผิดพลาดที่รายงานด้วยรหัส errno นั้นส่งผลให้เกิดข้อผิดพลาดในการออก ฉันอาจต้องทำแผนที่ที่สมเหตุสมผล
PSkocik

1
ว้าว! ฉันไม่ได้คาดหวังคำตอบที่ซับซ้อน ฉันจะลองใช้มันเป็นวิธีที่ดีในการดูว่าคำสั่งต่าง ๆ ทำงานอย่างไร ขอบคุณ
Anthony G - ความยุติธรรมสำหรับโมนิก้า

4

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


4

การอ้างอิงที่ดีที่สุดที่ฉันสามารถหาได้คือ: http://tldp.org/LDP/abs/html/exitcodes.html

ตามนี้:

1 เป็น catchall ทั่วไปสำหรับข้อผิดพลาดและฉันเคยเห็นมันใช้สำหรับข้อผิดพลาดที่ผู้ใช้กำหนด

2 ใช้สำหรับการสร้างเชลล์ในทางที่ผิดเช่นข้อผิดพลาดทางไวยากรณ์

ในการตอบคำถามของคุณโดยตรงสคริปต์ของคุณจะทำงานได้ดีโดยใช้รหัสข้อผิดพลาดที่สงวนไว้ซึ่งจะทำงานตามที่คาดไว้หากคุณจัดการข้อผิดพลาดตามรหัสข้อผิดพลาด = 1/2/3

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

ตัวเลือกอื่นที่คุณสามารถใช้ได้คือการสะท้อนข้อผิดพลาดหากมีตัวเลือกหนึ่งแล้วออกไปโดยสมมติว่าสคริปต์ของคุณเป็นไปตามระเบียบ Linux ของ "ไม่มีข่าวดีก็คือข่าวดี" และไม่มีอะไรประสบความสำเร็จ

if [ $? -ne 0 ];then
    echo "Error type"
    exit 1
fi

2

ตามคำตอบที่ฉันได้รับ (เป็นการยากที่จะเลือกมากกว่าหนึ่งข้อ) มันไม่เป็นอันตรายหากระบุข้อผิดพลาดบางประเภทโดยใช้รหัสออกที่ Bash ใช้ Bash (หรือ Unix shell อื่น ๆ ) จะไม่ทำอะไรเป็นพิเศษ (เช่นการเรียกใช้ตัวจัดการข้อยกเว้น) หากสคริปต์ผู้ใช้ออกจากหนึ่งในรหัสข้อผิดพลาดเหล่านี้

ดูเหมือนว่าผู้เขียนของคู่มือการทุบตีการเขียนสคริปต์ขั้นสูงเห็นด้วยกับความพยายาม BSD เพื่อสร้างมาตรฐานรหัสการออก ( sysexits.h) และเป็นการแนะนำว่าเมื่อผู้ใช้เขียนเชลล์สคริปต์พวกเขาไม่ได้ระบุรหัสทางออกที่ขัดแย้งกับรหัสทางออกที่กำหนดไว้ล่วงหน้าแล้ว ที่ใช้งานอยู่นั่นคือพวกเขา จำกัด รหัสออกที่กำหนดเองไว้ที่ 50 สถานะรหัสที่มีอยู่ในช่วง 64-113

ฉันขอขอบคุณความคิด (และเหตุผล) แต่ฉันต้องการถ้าผู้เขียนชัดเจนมากขึ้นว่าไม่เป็นอันตรายที่จะเพิกเฉยคำแนะนำ - นอกเหนือจากกรณีที่ผู้บริโภคของสคริปต์กำลังตรวจสอบข้อผิดพลาดเช่นตัวอย่างที่อ้างถึง 127 ( command not found)

ข้อกำหนด POSIX ที่เกี่ยวข้อง

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

ออกจากสถานะสำหรับคำสั่ง

แต่ละคำสั่งมีสถานะการออกที่สามารถมีอิทธิพลต่อพฤติกรรมของคำสั่งเชลล์อื่น ๆ สถานะการออกของคำสั่งที่ไม่ใช่ยูทิลิตี้จะได้รับการบันทึกไว้ในส่วนนี้ สถานะการออกของยูทิลิตี้มาตรฐานได้รับการบันทึกไว้ในส่วนที่เกี่ยวข้อง

หากไม่พบคำสั่งสถานะออกจะเป็น 127 หากพบชื่อคำสั่ง แต่ไม่ใช่ยูทิลิตี้ที่ปฏิบัติการได้สถานะออกจะเป็น 126 แอปพลิเคชันที่เรียกใช้ยูทิลิตี้โดยไม่ต้องใช้เชลล์ควรใช้ค่าสถานะการออกเหล่านี้ เพื่อรายงานข้อผิดพลาดที่คล้ายกัน

หากคำสั่งล้มเหลวระหว่างการขยายคำหรือการเปลี่ยนเส้นทางสถานะการออกของคำสั่งนั้นจะมากกว่าศูนย์

ภายในเพื่อจุดประสงค์ในการตัดสินใจว่าคำสั่งออกด้วยสถานะทางออกที่ไม่ใช่ศูนย์หรือไม่เชลล์จะรับรู้ค่าสถานะทั้งหมดที่ดึงมาสำหรับคำสั่งโดยเทียบเท่ากับฟังก์ชัน wait () ฟังก์ชัน WEXITSTATUS แมโคร (ตามที่กำหนดไว้ในระดับเสียงของระบบ POSIX.1-2008) เมื่อรายงานสถานะการออกด้วยพารามิเตอร์พิเศษ '?' เชลล์จะรายงานสถานะการออกเต็มแปดบิตที่มีอยู่ สถานะการออกของคำสั่งที่ยกเลิกเนื่องจากได้รับสัญญาณจะต้องรายงานมากกว่า 128

exitยูทิลิตี้

ตามที่อธิบายไว้ในส่วนอื่น ๆ ค่าสถานะการออกบางอย่างถูกสงวนไว้สำหรับการใช้งานพิเศษและควรใช้โดยแอปพลิเคชันเพื่อวัตถุประสงค์เหล่านั้นเท่านั้น:

  • 126 - พบไฟล์ที่จะดำเนินการ แต่ไม่ใช่ยูทิลิตี้ที่ใช้งานได้
  • 127 - ไม่พบยูทิลิตี้ที่จะดำเนินการ
  • >128 - คำสั่งถูกขัดจังหวะโดยสัญญาณ

ข้อมูลเพิ่มเติม

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

พยายามสร้างสถานะการออกเป็น 128

ใช้ Bash เวอร์ชัน 3.2.25 และ 4.2.46 ฉันพยายามโยน128 Invalid argument to exitข้อผิดพลาด แต่ทุกครั้งที่ฉันได้รับ 255 (สถานะออกจากช่วง) เช่นถ้าexit 3.14159ถูกเรียกใช้งานโดยเป็นส่วนหนึ่งของเชลล์สคริปต์หรือในเชลล์ลูกแบบโต้ตอบเชลล์จะออกด้วยรหัส255:

$ exit 3.14159
exit
bash: exit: 3.14159: numeric argument required

เพื่อความสนุกสนานยิ่งขึ้นฉันได้ลองใช้โปรแกรม C แบบง่าย ๆ แต่ในกรณีนี้ดูเหมือนว่าexit(3)ฟังก์ชั่นจะแปลง float เป็น int (3 ในกรณีนี้) ก่อนที่จะออก:

#include <stdlib.h>
main()
{
    exit(3.14159);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.