2008-12-26 46 views
5

我有幾個獨立的可執行Perl,PHP CLI腳本和C++程序,爲此我需要開發一個退出錯誤代碼策略。這些程序由其他程序使用我創建的用於在PHP中使用exec()的包裝類調用。所以,我將能夠得到一個錯誤代碼。根據該錯誤代碼,調用腳本需要做些事情。什麼是一個好的Linux退出錯誤代碼策略?

我已經做了一點研究,看起來像1-254(或者可能只是1-127)範圍內的任何事情都可能是用戶定義的錯誤代碼的公平遊戲。

我只是想知道其他人在這種情況下如何接近錯誤處理。

回答

8

唯一的約定是,你爲成功返回0,而對於錯誤返回0以外的東西。大多數着名的unix程序記錄了它們可以返回的各種返回代碼,您也應該如此。嘗試爲任何任意程序可能返回的所有可能的錯誤代碼創建一個通用列表並沒有多大意義,否則,最終會出現tens of thousands of them like some other OS's,即使如此,它並不總是涵蓋特定類型的您想要返回的錯誤。

因此,只要保持一致,並確保記錄您決定使用的任何方案。

6

1-127是可用的範圍。任何超過127的應該是「異常」退出 - 由信號終止。

當你在它的時候,考慮使用stdout而不是退出代碼。退出代碼是傳統用來表示成功,失敗,並可能是另一種狀態。而不是使用退出代碼,嘗試使用stdout的方式expr和wc使用它。然後你可以在調用者中使用反引號或類似的東西來提取結果。

+2

使用錯誤消息的stderr。 – iny 2008-12-26 15:09:28

3

Unix的宣言狀態 - 儘快

退出並大聲地對錯誤

或類似的東西

2

不要試圖編碼太多的意義進入退出值:詳細的狀態和錯誤報告應該按照Arkadiy的建議轉到stdout/stderr。

但是,我發現使用二進制數字對它們進行編碼僅僅表示出口值中的少數狀態非常有用。例如,假設您有以下做作含義:

0000 : 0 (no error) 
0001 : 1 (error) 
0010 : 2 (I/O error) 
0100 : 4 (user input error) 
1000 : 8 (permission error) 

然後,用戶輸入錯誤將有5(4 + 1)返回值,而日誌文件沒有寫權限可能有一個返回值爲11(8 + 2 + 1)。由於不同的含義是在返回值中獨立編碼的,因此可以通過檢查哪些位被設置來輕鬆查看發生了什麼。

作爲特殊情況,看是否有錯誤,你可以和1

返回代碼,通過這樣做,你可以編碼幾個不同的東西,在返回代碼,在一個明確的和簡單的方法。我只用它來做出簡單的決定,比如「應該重啓進程」,「返回值和相關日誌是否需要發送給管理員」等等。任何詳細的診斷信息都應該記錄到日誌或stdout/stderr。

1

正常退出狀態從0到255(請參閱Exit codes bigger than 255 posssible討論原因)。通常,狀態0表示成功;其他任何東西都是實現定義的錯誤。我知道一個通​​過退出狀態報告DBMS服務器狀態的程序;這是實現定義的退出狀態的特例。請注意,您可以定義程序狀態的實現。

我無法將它放入300個字符;否則這將是@ Arkadiy的答案的評論。

Arkadiy是正確的,在退出狀態字的一部分中,除零以外的值表示終止進程的信號,第8位通常表示核心轉儲,但退出狀態的該部分不同於主0..255狀態。然而,當一個進程因信號而死亡時,外殼(無論它是哪個外殼)都會出現問題。有8位數據要顯示16位數據,這總是很棘手。殼看起來要做的是取信號碼並加128。因此,如果一個進程由於中斷而停止(信號編號2,SIGINT),shell將退出狀態報告爲130.但是,內核將狀態報告爲0x0002; shell已經修改了內核報告的內容。

下面的C代碼演示了這一點。有兩個程序

  • suicide它會使用您選擇的信號(默認爲中斷)來殺死它自己。
  • exitstatus它運行一個命令(如suicide)並報告內核退出狀態。

這裏的suicide.c

/* 
@(#)File:   $RCSfile: suicide.c,v $ 
@(#)Version:  $Revision: 1.2 $ 
@(#)Last changed: $Date: 2008/12/28 03:45:18 $ 
@(#)Purpose:  Commit suicide using kill() 
@(#)Author:   J Leffler 
@(#)Copyright:  (C) JLSS 2008 
@(#)Product:  :PRODUCT: 
*/ 

/*TABSTOP=4*/ 

#if __STDC_VERSION__ >= 199901L 
#define _XOPEN_SOURCE 600 
#else 
#define _XOPEN_SOURCE 500 
#endif /* __STDC_VERSION__ */ 

#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include "stderr.h" 

static const char usestr[] = "[-V][-s signal]"; 

#ifndef lint 
/* Prevent over-aggressive optimizers from eliminating ID string */ 
extern const char jlss_id_suicide_c[]; 
const char jlss_id_suicide_c[] = "@(#)$Id: suicide.c,v 1.2 2008/12/28 03:45:18 jleffler Exp $"; 
#endif /* lint */ 

int main(int argc, char **argv) 
{ 
    int signum = SIGINT; 
    int opt; 
    char *end; 

    err_setarg0(argv[0]); 

    while ((opt = getopt(argc, argv, "Vs:")) != -1) 
    { 
     switch (opt) 
     { 
     case 's': 
      signum = strtol(optarg, &end, 0); 
      if (*end != '\0' || signum <= 0) 
       err_error("invalid signal number %s\n", optarg); 
      break; 
     case 'V': 
      err_version("SUICIDE", &"@(#)$Revision: 1.2 $ ($Date: 2008/12/28 03:45:18 $)"[4]); 
      break; 
     default: 
      err_usage(usestr); 
      break; 
     } 
    } 
    if (optind != argc) 
     err_usage(usestr); 
    kill(getpid(), signum); 
    return(0); 
} 

而這裏的exitstatus.c

/* 
@(#)File:   $RCSfile: exitstatus.c,v $ 
@(#)Version:  $Revision: 1.2 $ 
@(#)Last changed: $Date: 2008/12/28 03:45:18 $ 
@(#)Purpose:  Run command and report 16-bit exit status 
@(#)Author:   J Leffler 
@(#)Copyright:  (C) JLSS 2008 
@(#)Product:  :PRODUCT: 
*/ 

/*TABSTOP=4*/ 

#if __STDC_VERSION__ >= 199901L 
#define _XOPEN_SOURCE 600 
#else 
#define _XOPEN_SOURCE 500 
#endif /* __STDC_VERSION__ */ 

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include "stderr.h" 

#ifndef lint 
/* Prevent over-aggressive optimizers from eliminating ID string */ 
extern const char jlss_id_exitstatus_c[]; 
const char jlss_id_exitstatus_c[] = "@(#)$Id: exitstatus.c,v 1.2 2008/12/28 03:45:18 jleffler Exp $"; 
#endif /* lint */ 

int main(int argc, char **argv) 
{ 
    pid_t pid; 

    err_setarg0(argv[0]); 

    if (argc < 2) 
     err_usage("cmd [args...]"); 

    if ((pid = fork()) < 0) 
     err_syserr("fork() failed: "); 
    else if (pid == 0) 
    { 
     /* Child */ 
     execvp(argv[1], &argv[1]); 
     return(1); 
    } 
    else 
    { 
     pid_t corpse; 
     int status; 
     corpse = waitpid(pid, &status, 0); 
     if (corpse != pid) 
      err_syserr("waitpid() failed: "); 
     printf("0x%04X\n", status); 
    } 
    return(0); 
} 

遺漏碼,stderr.cstderr.h,可以很容易地在本質上我的任何出版計劃中找到。如果您急需它,請從程序SQLCMD處獲取IIUG Software Archive;或者,通過電子郵件與我聯繫(見我的個人資料)。

相關問題