มีรหัสสถานะการออกมาตรฐานใน Linux หรือไม่


308

กระบวนการที่ถือว่าเสร็จสมบูรณ์อย่างถูกต้องใน Linux หากสถานะการออกเป็น 0

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

มีรหัสทางออกมาตรฐานสำหรับกระบวนการใน Linux หรือไม่


6
หากคุณกำลังมองหาสิ่งที่เรียกว่า "หมายเลขข้อผิดพลาดของระบบ" ส่งคืนโดยฟังก์ชันของระบบดูที่นี่ที่errno
marinara

คำตอบ:


86

8 บิตของโค้ดส่งคืนและ 8 บิตของจำนวนสัญญาณการทำลายจะถูกรวมกันเป็นค่าเดียวของการส่งคืนจากwait(2)& co .

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

int main() {
    int status;

    pid_t child = fork();
    if (child <= 0)
        exit(42);
    waitpid(child, &status, 0);
    if (WIFEXITED(status))
        printf("first child exited with %u\n", WEXITSTATUS(status));
    /* prints: "first child exited with 42" */

    child = fork();
    if (child <= 0)
        kill(getpid(), SIGSEGV);
    waitpid(child, &status, 0);
    if (WIFSIGNALED(status))
        printf("second child died with %u\n", WTERMSIG(status));
    /* prints: "second child died with 11" */
}

คุณจะกำหนดสถานะการออกได้อย่างไร โดยปกติแล้วเชลล์จะเก็บโค้ดส่งคืน 8 บิตเท่านั้น แต่ตั้งค่าบิตสูงหากกระบวนการนั้นถูกยกเลิกแบบผิดปกติ

$ sh -c 'exit 42'; echo $
42
$ sh -c 'kill -SEGV $$'; echo $
การแบ่งส่วนความผิด
139
$ expr 139 - 128
11

หากคุณเห็นสิ่งอื่นนอกเหนือจากนี้โปรแกรมอาจมีSIGSEGVตัวจัดการสัญญาณซึ่งเรียกได้exitตามปกติดังนั้นจึงไม่ได้รับสัญญาณจากการฆ่า (โปรแกรมสามารถเลือกที่จะจัดการสัญญาณใด ๆ นอกเหนือจากSIGKILLและSIGSTOP)


8
เมื่อพิจารณาถึงคำถามที่ปรากฏขึ้นในตอนนี้สิ่งนี้ดูเหมือนจะไม่เป็นคำตอบที่มีประโยชน์ที่สุด (และยอมรับแล้ว)
David J.

332

ส่วนที่ 1: คู่มือการสคริปต์การทุบตีขั้นสูง

เช่นเคยคู่มือการใช้สคริปต์การทุบตีขั้นสูงมีข้อมูลที่ยอดเยี่ยม : (ลิงก์นี้มีคำตอบอื่น แต่เป็น URL ที่ไม่ใช่แบบบัญญัติ)

1: รับทั้งหมดสำหรับข้อผิดพลาดทั่วไป
ที่ 2:วัตถุประสงค์ของ builtins เปลือก (ตามเอกสารทุบตี)
126: คำสั่งเรียกไม่สามารถรัน
127: คำสั่ง "ไม่พบ"
128: อาร์กิวเมนต์ไม่ถูกต้องเพื่อออก
128 + n: สัญญาณผิดพลาดร้ายแรง "n"
255:ทางออก สถานะอยู่นอกช่วง (ออกจะใช้จำนวนเต็มเท่านั้นในช่วง 0 - 255)

ส่วนที่ 2: sysexits.h

การอ้างอิง ABSG sysexits.hอ้างอิง

บน Linux:

$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h

/*
 * Copyright (c) 1987, 1993
 *  The Regents of the University of California.  All rights reserved.

 (A whole bunch of text left out.)

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

#define EX__MAX 78      /* maximum listed value */

5
โปรดทราบว่าในบางรสชาติของยูนิกซ์คำสั่งบางคำสั่งใช้สถานะการออก 2 เพื่อระบุสิ่งอื่น ๆ ตัวอย่างเช่นการใช้งาน grep จำนวนมากใช้สถานะการออกเป็น 2 เพื่อระบุข้อผิดพลาดและใช้สถานะการออกเป็น 1 เพื่อหมายความว่าไม่พบบรรทัดที่เลือก
NamshubWriter

3
ใน BSD มีหน้าคนสรุปข้อมูลจาก sysexits.h:man sysexits
georgebrock

6
สิ่งที่ @NamshubWriter พูด สถานะการออก 2เป็น go-to สากลสำหรับการใช้งานบรรทัดคำสั่งที่ไม่ถูกต้องในยูทิลิตี Unix ไม่เพียง แต่ใน "บางรสชาติของยูนิกซ์" แต่โดยทั่วไป ส่วนหัวที่แสดงในคำตอบนี้ไม่ได้สะท้อนให้เห็นถึงการประชุมที่เกิดขึ้นจริงในขณะนี้หรือเมื่อมันถูกเขียนในปี 1987
อเล็กซิส

ABS ไม่ใช่ "ยอดเยี่ยม" โปรดอ่านเรื่อง; มันไม่ยากเลยที่จะค้นหาคำวิจารณ์
tripleee

แต่รหัสแหล่งที่มาอย่างเป็นทางการที่แท้จริงอยู่sysexits.hที่ไหน หน้าคนทุกคนที่ช่วยให้การอ้างอิงเป็นเพียงร้อยแก้ว ยกตัวอย่างเช่นมันอ้างอิงEX_OKแต่ไม่ได้กำหนดไว้ในทางปกติเช่นรหัสอื่น ๆ มีอะไรอีกบ้างที่ขาดหายไป?
Garret Wilson

71

'1' >>> Catchall สำหรับข้อผิดพลาดทั่วไป

'2' >>> การใช้งานเชลล์บิลด์ในทางที่ผิด (ตามเอกสาร Bash)

'126' >>> การเรียกใช้คำสั่งไม่สามารถดำเนินการได้

'127' >>> "ไม่พบคำสั่ง"

'128' >>> อาร์กิวเมนต์ไม่ถูกต้องในการออก

'128 + n' >>> สัญญาณข้อผิดพลาดร้ายแรง "n"

'130' >>> สคริปต์ถูกยกเลิกโดย Control-C

'255' >>> ออกจากสถานะนอกระยะ

นี่คือทุบตี อย่างไรก็ตามสำหรับแอปพลิเคชันอื่นมีรหัสการออกต่างกัน


1
ดูเหมือนว่าคุณทั้งคู่จะตอบในนาทีเดียว ท่าเตียนจะต้องค่อนข้างเร็วในการดูลิงก์ของคุณและวางลงใน.
นาธานเฟลล์แมน

6
โปรดทราบว่า 'control-C ถัวเฉลี่ย 130' สอดคล้องกับ '128 + n' สำหรับสัญญาณ n; control-C สร้าง SIGINT ซึ่งเป็นสัญญาณ 2
Jonathan Leffler

3
ดูเหมือนว่าจะคัดลอกมาจาก ABS โดยไม่มีการระบุแหล่งที่มา (เราสามารถบอกได้เพราะ ABS มีข้อมูลที่ไม่ถูกต้องหรืออย่างน้อยทำให้เข้าใจผิด)
tripleee

4
เหล่านี้จะสงวนรหัสทางออกตามขั้นสูงทุบตี Scripting คู่มือ นั่นหมายความว่าค่าเหล่านี้จึงควรหลีกเลี่ยงสำหรับผู้ใช้ระบุพารามิเตอร์ทางออก
ingyhere

53

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

นี่คือการประชุมสถานะการออกจริงที่ยาวนานและยาวนานสำหรับการยกเลิกตามปกตินั่นคือไม่ใช่สัญญาณ:

  • ออกจากสถานะ 0: สำเร็จ
  • สถานะการออก 1: "ล้มเหลว" ตามที่กำหนดโดยโปรแกรม
  • สถานะการออก 2: ข้อผิดพลาดการใช้บรรทัดคำสั่ง

ตัวอย่างเช่นdiffส่งคืน 0 หากไฟล์ที่เปรียบเทียบนั้นเหมือนกันและ 1 หากไฟล์ต่างกัน โดยการประชุมยาวนานโปรแกรมยูนิกซ์กลับสถานะออก 2 เมื่อเรียกไม่ถูกต้อง (ตัวเลือกที่ไม่รู้จักจำนวนที่ไม่ถูกต้องของการขัดแย้ง ฯลฯ ) ยกตัวอย่างเช่นdiff -N, grep -Yหรือdiff a b cจะส่งผลใน$?การเป็นชุด 2 นี้เป็นและได้รับการปฏิบัติตั้งแต่ที่ วันแรก ๆ ของ Unix ในปี 1970

คำตอบที่ได้รับการยอมรับอธิบายถึงสิ่งที่เกิดขึ้นเมื่อมีคำสั่งถูกยกเลิกโดยสัญญาณ ในช่วงสั้น ๆ เลิกจ้างเนื่องจากผลสัญญาณ uncaught 128+[<signal number>ในสถานะออก เช่นการยกเลิกด้วยSIGINT( สัญญาณ 2 ) ส่งผลให้สถานะออก 130

หมายเหตุ

  1. คำตอบหลายคำจำกัดความสถานะการออก 2 เป็น "การใช้ผิดพลาดของ bash builtins" สิ่งนี้ใช้เฉพาะเมื่อbash (หรือ bash script) ออกจากสถานะ 2 พิจารณาว่าเป็นกรณีพิเศษของการใช้งานที่ผิดพลาด

  2. ในที่sysexits.hกล่าวถึงในคำตอบที่ได้รับความนิยมมากที่สุดสถานะการออกEX_USAGE("ข้อผิดพลาดการใช้บรรทัดคำสั่ง") ถูกกำหนดให้เป็น 64 แต่สิ่งนี้ไม่ได้สะท้อนถึงความเป็นจริง: ฉันไม่ได้ตระหนักถึงยูทิลิตี Unix ทั่วไปใด ๆ ) การอ่านอย่างละเอียดของซอร์สโค้ดแสดงให้เห็นว่าsysexits.hเป็นแรงบันดาลใจแทนที่จะสะท้อนการใช้งานจริง:

     *    This include file attempts to categorize possible error
     *    exit statuses for system programs, notably delivermail
     *    and the Berkeley network.
    
     *    Error numbers begin at EX__BASE [64] to reduce the possibility of 
     *    clashing with oth­er exit statuses that random programs may 
     *    already return. 
    

    กล่าวอีกนัยหนึ่งคำจำกัดความเหล่านี้ไม่ได้สะท้อนให้เห็นถึงการปฏิบัติทั่วไปในเวลา (1993) แต่ไม่เข้ากันกับมันโดยเจตนา น่าเสียดายมาก


สิ่งที่ควรมีผลตอบแทนจากโปรแกรมเมื่อมันไม่เลิกจ้างโดยการจับมือจับ SIGINT / Ctrl-C? ยังเป็น 130 การใช้งานเชลล์อื่นนอกเหนือจากสสาร bash หรือไม่?
Gringo Suave

1
เชลล์ที่เรียกใช้งานโปรแกรมไม่เกี่ยวข้อง ในทางทฤษฎีกระบวนการสามารถเลือกที่จะออกด้วยสถานะที่แตกต่างกันขึ้นอยู่กับกระบวนการหลัก แต่ฉันไม่เคยได้ยินกรณีที่เกิดขึ้น
alexis

1
หากโปรแกรมจับ SIGINT ล้างข้อมูลและออกแล้วสถานะจะเป็นสิ่งที่สมเหตุสมผลสำหรับโปรแกรม ตัวอย่างเช่นmoreจะรีเซ็ตโหมดเทอร์มินัลและออกด้วยสถานะ 0 (คุณสามารถลองได้)
alexis

1
คำตอบนี้แสดงถึงระดับมาตรฐานที่สูงกว่าสิ่งที่เป็นจริง ไม่มีมาตรฐานที่เหมาะสมของความหมายของค่า 2 และการปฏิบัติจริงนั้นคาดเดาได้หลากหลายมาก มันเป็นความจริงที่เครื่องมือจำนวนมากส่งคืน 2 สำหรับการใช้งานที่ไม่เหมาะสม แต่ไม่ได้กำหนดอย่างชัดเจนว่า "การใช้งานที่ไม่เหมาะสม" หมายถึงอะไรและอื่น ๆ อีกมากมายไม่ปฏิบัติตามอนุสัญญานี้
tripleee

@tripleee "tools" ไม่ได้ถูกกำหนดอย่างดีเช่นกัน! :-) แน่นอนว่าทุกคนสามารถเขียนโปรแกรมบรรทัดคำสั่งได้และสามารถส่งคืนสิ่งใดก็ได้ แต่เครื่องมือ "บรรทัดคำสั่ง Unix" แบบเก่าซึ่งใช้เวลานานกว่า Linux หรือเนื้อหาของ GNU coreutils ค่อนข้างมาก สอดคล้องกับสิ่งนี้ หากคุณคิดอย่างอื่นโปรดตั้งชื่อเครื่องมือบางอย่างในกลุ่มนี้ที่ไม่ได้ใช้สถานะ 2 ด้วยวิธีนี้ นอกจากนี้ "การใช้งานที่ไม่เหมาะสม" เป็นคำของคุณ (และฉันยอมรับว่าเป็นคำที่คลุมเครือ); ฉันเขียน "ข้อผิดพลาดในการใช้บรรทัดคำสั่ง" ซึ่งค่อนข้างเจาะจง: ตัวเลือกที่ไม่มีอยู่หรือไม่เข้ากันจำนวนที่ไม่ถูกต้องของอาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกอื่น ๆ
alexis

25

ไม่มีรหัสออกมาตรฐานนอกเหนือจาก 0 หมายถึงความสำเร็จ ไม่ใช่ศูนย์ไม่ได้แปลว่าล้มเหลวเช่นกัน

stdlib.h กำหนดEXIT_FAILUREเป็น 1 และEXIT_SUCCESSเป็น 0 แต่นั่นเกี่ยวกับ

11 บน segfault นั้นน่าสนใจเนื่องจาก 11 คือหมายเลขสัญญาณที่เคอร์เนลใช้เพื่อฆ่ากระบวนการในกรณีที่ segfault อาจมีกลไกบางอย่างไม่ว่าจะในเคอร์เนลหรือในเชลล์ซึ่งแปลว่าเป็นรหัสออก


20

sysexits.hมีรายการรหัสทางออกมาตรฐาน ดูเหมือนว่าจะย้อนกลับไปอย่างน้อยปี 1993 และโครงการขนาดใหญ่บางอย่างเช่น Postfix ใช้มันดังนั้นฉันคิดว่ามันเป็นวิธีที่จะไป

จากหน้าคน OpenBSD:

ตามสไตล์ (9) มันเป็นวิธีปฏิบัติที่ดีในการเรียกทางออก (3) ที่มีค่าวัตถุเพื่อบ่งชี้ถึงสภาพความล้มเหลวเมื่อสิ้นสุดโปรแกรม ควรใช้รหัสทางออกที่กำหนดไว้ล่วงหน้าจาก sysexits ดังนั้นผู้เรียกกระบวนการสามารถรับการประมาณคร่าวๆเกี่ยวกับคลาสความล้มเหลวโดยไม่ต้องค้นหาซอร์สโค้ด

8

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

ยิ่งกว่าความเป็นจริง 0 หมายถึงความสำเร็จหรือความล้มเหลว 1 หมายถึงความล้มเหลวทั่วไปหรือความสำเร็จ 2 หมายถึงความล้มเหลวทั่วไปหากทั้ง 1 และ 0 ใช้สำหรับความสำเร็จ แต่อาจประสบความสำเร็จเช่นกัน

คำสั่ง diff ให้ 0 ถ้าไฟล์ที่เปรียบเทียบเหมือนกัน 1 ถ้ามันต่างกันและ 2 ถ้าไบนารีต่างกัน 2 ยังหมายถึงความล้มเหลว คำสั่ง less ให้ 1 สำหรับความล้มเหลวเว้นแต่คุณจะไม่สามารถระบุอาร์กิวเมนต์ในกรณีนี้มันจะออกจาก 0 แม้จะล้มเหลว

คำสั่ง more และคำสั่ง spell ให้ 1 สำหรับความล้มเหลวเว้นแต่ความล้มเหลวเป็นผลมาจากการปฏิเสธสิทธิ์ไฟล์ที่ไม่มีอยู่หรือพยายามอ่านไดเรกทอรี ในกรณีเหล่านี้พวกเขาออกจาก 0 แม้จะล้มเหลว

จากนั้นคำสั่ง expr จะให้ 1 สำหรับ sucess ยกเว้นว่าเอาต์พุตเป็นสตริงว่างหรือศูนย์ในกรณีนี้ 0 คือ sucess 2 และ 3 เป็นความล้มเหลว

จากนั้นมีหลายกรณีที่ความสำเร็จหรือความล้มเหลวไม่ชัดเจน เมื่อ grep ล้มเหลวในการค้นหารูปแบบมันจะออกจาก 1 แต่จะออกจาก 2 สำหรับความล้มเหลวของแท้ (เช่นปฏิเสธสิทธิ์) Klist ยังออกจาก 1 เมื่อไม่สามารถหาตั๋วได้แม้ว่านี่จะไม่ใช่ความล้มเหลวอีกต่อไปกว่าเมื่อ grep ไม่พบรูปแบบหรือเมื่อคุณมีไดเรกทอรีว่างเปล่า

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


ฉันกำลังจะชี้ให้เห็นพฤติกรรมของ diff ด้วยเช่นกัน wget ยังมีข้อผิดพลาดโดยละเอียด (เช่น 6 สำหรับความล้มเหลวในการตรวจสอบความถูกต้อง) แต่จากนั้นพวกเขาใช้ 1 = ข้อผิดพลาดทั่วไป 2..n = ข้อผิดพลาดเฉพาะ
PypeBros

5

โปรแกรมส่งคืนรหัสทางออก 16 บิต หากโปรแกรมถูกฆ่าด้วยสัญญาณดังนั้นลำดับสูงจะมีสัญญาณที่ใช้มิฉะนั้นไบต์ลำดับต่ำคือสถานะทางออกที่ส่งคืนโดยโปรแกรมเมอร์

รหัสทางออกนั้นถูกกำหนดให้กับตัวแปรสถานะ $ อย่างไร นั้นขึ้นอยู่กับเปลือก Bash ใช้สถานะต่ำกว่า 7 บิตจากนั้นใช้ 128 + (สัญญาณ nr) เพื่อระบุสัญญาณ

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


3

รหัสทางออก Unix มาตรฐานถูกกำหนดโดย sysexits.h ตามที่ผู้โพสต์คนอื่นพูดถึง รหัสทางออกเดียวกันถูกใช้โดยไลบรารีแบบพกพาเช่น Poco - นี่คือรายการของพวกเขา:

http://pocoproject.org/docs/Poco.Util.Application.html#16218

สัญญาณ 11 คือสัญญาณ SIGSEGV (การละเมิดกลุ่ม) ซึ่งแตกต่างจากรหัสส่งคืน สัญญาณนี้ถูกสร้างขึ้นโดยเคอร์เนลเพื่อตอบสนองต่อการเข้าถึงเพจที่ไม่ดีซึ่งทำให้โปรแกรมหยุดทำงาน รายการของสัญญาณสามารถพบได้ในหน้าคนส่งสัญญาณ (เรียกใช้ "สัญญาณคน")


1

เมื่อ Linux คืนค่า 0 นั่นหมายถึงความสำเร็จ สิ่งอื่นหมายถึงความล้มเหลวแต่ละโปรแกรมมีรหัสทางออกของตนเองดังนั้นจึงค่อนข้างนานที่จะแสดงรายการทั้งหมด ... !

เกี่ยวกับรหัสข้อผิดพลาด 11 รายการเป็นหมายเลขข้อผิดพลาดการแบ่งกลุ่มซึ่งส่วนใหญ่หมายความว่าโปรแกรมเข้าถึงตำแหน่งหน่วยความจำที่ไม่ได้รับมอบหมาย


1
มันเป็น 11 เสมอเพราะเคอร์เนลฆ่ามันและกำหนด "exit value" เช่นเดียวกันความผิดพลาดประเภทอื่นจะได้รับค่าการออกเท่ากันเสมอ
Alex Gartrell
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.