Shell ExitCodes大于255,可能吗?

Shell ExitCodes大于255,可能吗?,shell,operating-system,exit-code,Shell,Operating System,Exit Code,如果是,在哪个操作系统上,shell或其他什么 考虑以下java程序(我使用java只是作为一个示例,任何语言都可以解决这个问题,这更多是关于操作系统的): 在Linux和bash上运行时,它总是返回小于等于255的值,例如(echo$?打印上一个执行命令的退出代码) 编辑:下面的(唯一的,到目前为止)答案完全解释了Unix上发生的事情。我仍然在想其他操作系统。使用wait()或waitpid() 在Unix和使用POSIX函数(如和)的衍生工具上是不可能的。返回的退出状态信息由两个8位字段组

如果是,在哪个操作系统上,shell或其他什么

考虑以下java程序(我使用java只是作为一个示例,任何语言都可以解决这个问题,这更多是关于操作系统的):

在Linux和bash上运行时,它总是返回小于等于255的值,例如(
echo$?
打印上一个执行命令的退出代码)


编辑:下面的(唯一的,到目前为止)答案完全解释了Unix上发生的事情。我仍然在想其他操作系统。

使用
wait()
waitpid()
在Unix和使用POSIX函数(如和)的衍生工具上是不可能的。返回的退出状态信息由两个8位字段组成,一个包含退出状态,另一个包含关于死亡原因的信息(0表示在程序控制下有序退出,其他值表示信号杀死它,并指示是否转储内核)

使用
sigaction()
SA_SIGINFO
如果您努力工作,并阅读和的POSIX规范,您会发现您可以通过子进程获得传递给
exit()
的32位值。然而,这并不是完全直截了当的

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

static siginfo_t sig_info = { 0 };
static volatile sig_atomic_t sig_num = 0;
static void *sig_ctxt = 0;

static void catcher(int signum, siginfo_t *info, void *vp)
{
    sig_num = signum;
    sig_info = *info;
    sig_ctxt = vp;
}

static void set_handler(int signum)
{
    struct sigaction sa;
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = catcher;
    sigemptyset(&sa.sa_mask);

    if (sigaction(signum, &sa, 0) != 0)
    {
        int errnum = errno;
        fprintf(stderr, "Failed to set signal handler (%d: %s)\n", errnum, strerror(errnum));
        exit(1);
    }
}

static void prt_interrupt(FILE *fp)
{
    if (sig_num != 0)
    {
        fprintf(fp, "Signal %d from PID %d (status 0x%.8X; UID %d)\n",
                sig_info.si_signo, (int)sig_info.si_pid, sig_info.si_status,
                (int)sig_info.si_uid);
        sig_num = 0;
    }
}

static void five_kids(void)
{
    const int base = 0xCC00FF40;
    for (int i = 0; i < 5; i++)
    {
        pid_t pid = fork();
        if (pid < 0)
            break;
        else if (pid == 0)
        {
            printf("PID %d - exiting with status %d (0x%.8X)\n",
                   (int)getpid(), base + i, base + i);
            exit(base + i);
        }
        else
        {
            int status = 0;
            pid_t corpse = wait(&status);
            if (corpse != -1)
                printf("Child: %d; Corpse: %d; Status = 0x%.4X - waited\n", pid, corpse, (status & 0xFFFF));
            struct timespec nap = { .tv_sec = 0, .tv_nsec = 1000000 }; // 1 millisecond
            nanosleep(&nap, 0);
            prt_interrupt(stdout);
            fflush(0);
        }
    }
}

int main(void)
{
    set_handler(SIGCHLD);
    five_kids();
}
删除对
nanosleep()
的一毫秒调用后,输出很可能如下所示:

$ sigexit73
sigexit23
PID 26621 - exiting with status -872349888 (0xCC00FF40)
Signal 20 from PID 26621 (status 0xCC00FF40; UID 501)
Child: 26622; Corpse: 26621; Status = 0x4000 - waited
PID 26622 - exiting with status -872349887 (0xCC00FF41)
PID 26623 - exiting with status -872349886 (0xCC00FF42)
Signal 20 from PID 26622 (status 0xCC00FF41; UID 501)
Child: 26624; Corpse: 26623; Status = 0x4200 - waited
Signal 20 from PID 26623 (status 0xCC00FF42; UID 501)
Child: 26625; Corpse: 26622; Status = 0x4100 - waited
PID 26624 - exiting with status -872349885 (0xCC00FF43)
PID 26625 - exiting with status -872349884 (0xCC00FF44)
$
请注意,这里只有三行开始
信号
,也只有三行结束
等待
;一些信号和退出状态丢失。这可能是因为设置到父进程的
SIGCHLD
信号之间存在定时问题

然而,关键点是,当代码使用
sigaction()
SIGCHLD
SA_sigino
跟踪状态时,可以在
exit()
状态下传输4字节的数据


为了记录在案,测试是在运行macOS Mojave 10.14.6的MacBook Pro上进行的,使用的是GCC 9.2.0和XCode 11.3.1。代码也可以在GitHub上的my(Stack Overflow Questions)存储库中的子目录下的文件
sigexit73.c
中找到。

Windows有更多的退出代码,超过14000个。(我相信你经常在自己的屏幕上看到其中的一些)

下面是:


在现代Windows上,操作系统本身和默认控制台外壳(
CMD.EXE
)至少在整个32位带符号整数范围内接受并显示退出代码。在
CMD.EXE
中运行上面的示例会给出您要求的退出代码:

> java ExitCode 2
> echo %errorlevel%
2

> java ExitCode 128
> echo %errorlevel%
128

> java ExitCode 255
> echo %errorlevel%
255

> java ExitCode 256
> echo %errorlevel%
256

> java ExitCode 65536
> echo %errorlevel%
65536

Windows实际上没有Unix信号的概念,也没有试图劫持退出代码来添加额外的信息,因此只要您的shell(或任何程序最终读取退出代码)也不这样做,您就应该返回返回的退出代码。幸运的是,使用Microsoft C运行时的程序(包括使用MS Visual C++编译的所有程序)保留退出进程的退出代码。

您所说的是标准Windows API返回的错误代码。OP想知道他/她自己的程序可以返回哪些错误代码。不,windows支持32位退出代码=>超过40亿可能会说“超过9000”!这是因为返回了一个无符号短整数(8位)。0000000 = 0 11111111 = 255
$ sigexit73
PID 26599 - exiting with status -872349888 (0xCC00FF40)
Signal 20 from PID 26599 (status 0xCC00FF40; UID 501)
Child: 26600; Corpse: 26599; Status = 0x4000 - waited
PID 26600 - exiting with status -872349887 (0xCC00FF41)
Signal 20 from PID 26600 (status 0xCC00FF41; UID 501)
Child: 26601; Corpse: 26600; Status = 0x4100 - waited
PID 26601 - exiting with status -872349886 (0xCC00FF42)
Signal 20 from PID 26601 (status 0xCC00FF42; UID 501)
Child: 26602; Corpse: 26601; Status = 0x4200 - waited
PID 26602 - exiting with status -872349885 (0xCC00FF43)
Signal 20 from PID 26602 (status 0xCC00FF43; UID 501)
Child: 26603; Corpse: 26602; Status = 0x4300 - waited
PID 26603 - exiting with status -872349884 (0xCC00FF44)
Signal 20 from PID 26603 (status 0xCC00FF44; UID 501)
$
$ sigexit73
sigexit23
PID 26621 - exiting with status -872349888 (0xCC00FF40)
Signal 20 from PID 26621 (status 0xCC00FF40; UID 501)
Child: 26622; Corpse: 26621; Status = 0x4000 - waited
PID 26622 - exiting with status -872349887 (0xCC00FF41)
PID 26623 - exiting with status -872349886 (0xCC00FF42)
Signal 20 from PID 26622 (status 0xCC00FF41; UID 501)
Child: 26624; Corpse: 26623; Status = 0x4200 - waited
Signal 20 from PID 26623 (status 0xCC00FF42; UID 501)
Child: 26625; Corpse: 26622; Status = 0x4100 - waited
PID 26624 - exiting with status -872349885 (0xCC00FF43)
PID 26625 - exiting with status -872349884 (0xCC00FF44)
$
> java ExitCode 2
> echo %errorlevel%
2

> java ExitCode 128
> echo %errorlevel%
128

> java ExitCode 255
> echo %errorlevel%
255

> java ExitCode 256
> echo %errorlevel%
256

> java ExitCode 65536
> echo %errorlevel%
65536