什么是一个好的Linux退出错误代码策略?

我有几个独立的可执行Perl,PHP CLI脚本和C ++程序,我需要开发一个退出错误代码策略。 这些程序由其他程序使用我创build的用于在PHP中使用exec()的封装类来调用。 所以,我将能够得到一个错误代码。 基于那个错误代码,调用脚本将需要做一些事情。

我已经做了一些研究,看起来1-254(或者只是1-127)范围内的任何事情对于用户定义的错误代码来说都是公平的游戏。

我只是想知道在这种情况下其他人是如何处理error handling的。

Solutions Collecting From Web of "什么是一个好的Linux退出错误代码策略?"

唯一的约定是,您返回0成功,而不是零的错误。 大多数着名的unix程序记录了它们可以返回的各种返回代码,你也应该这样做。 尝试为所有可能的错误代码建立一个通用的列表,使任何程序可能返回都没有什么意义,否则最终会有成千上万个类似于其他操作系统的错误代码,即使如此,它也不会总是覆盖你想要返回的特定类型的错误。

所以只要保持一致,并确保记录你决定使用的任何方案。

1-127是可用的范围。 任何超过127个应该是“异常”退出 – 信号终止。

当你在这个时候,考虑使用stdout而不是退出代码。 退出代码是传统用来表示成功,失败的,可能是另外一种状态。 而不是使用退出代码,尝试使用stdout的方式expr和wc使用它。 然后你可以在调用者中使用反引号或类似的东西来提取结果。

unix宣言声明 –

尽快出口,尽可能大的错误

或类似的东西

不要试图将过多的含义编码到退出值中:详细的状态和错误报告应该按照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)。 由于不同的含义在返回值中被独立地编码,所以通过检查哪些位被设置可以容易地看到发生了什么。

作为一个特殊情况,要查看是否有错误,可以将AND返回码与1进行比较。

通过这样做,你可以用简单明了的方式在返回代码中编码几个不同的东西。 我只是用这个来做简单的决定,比如“重启进程”,“返回值和相关日志是否需要发送给管理员”等等。 任何详细的诊断信息都应该记录到日志或stdout / stderr。

正常的退出状态从0到255(参见退出代码大于255可用于讨论原因)。 通常状态0表示成功; 其他任何东西都是实现定义的错误。 我知道一个通​​过退出状态报告DBMS服务器状态的程序; 这是实现定义的退出状态的特例。 请注意,您可以定义程序状态的实现。

我不能把这300个字符; 否则这将是@ Arkadiy的答案的评论。

Arkadiy是正确的,在退出状态字的一个部分中,除零之外的值表示终止进程的信号,第8位通常表示核心转储,但退出状态的这一部分不同于主要的0..255状态。 然而,当一个进程因信号而死亡时,外壳(无论是哪个外壳)都会出现问题。 有8位数据要显示16位数据,这总是很棘手的。 炮弹似乎做的是取信号码,并加128。 因此,如果一个进程由于中断而停止(信号编号2,SIGINT),shell将退出状态报告为130.但是,内核将状态报告为0x0002; shell已经修改了内核报告的内容。

以下C代码演示了这一点。 有两个程序

  • suicide使用您选择的信号suicide (默认中断)。
  • 运行命令(如suicide )的exitstatus并报告内核退出状态。

这里是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很容易在我的任何已发布的程序中找到。 如果您迫切需要,请从IIUG软件存档的 SQLCMD程序中获取; 或者,通过电子邮件与我联系(见我的个人资料)。