【问题标题】:Exit status of $? using python when segmentation fault occured$的退出状态?发生分段错误时使用python
【发布时间】:2018-11-26 22:38:06
【问题描述】:

我需要使用 python3 执行echo $? 并捕获退出状态。我特别需要这个来捕获Segmentation fault (core dumped) 状态。 我试过了:

>>> os.system('echo $?')
0
0

得到0 0。另外,对于段错误,

>>> os.system('./a.out')
Segmentation fault (core dumped)
35584

在上面的命令之后,我又得到了:

>>> os.system('echo $?')
0
0

另外,为什么0 会被打印两次? 我浏览了 python-3 的文档,上面写着:

os.system(命令)

在 Unix 上,返回值是以 wait() 指定的格式编码的进程的退出状态。注意POSIX并没有指定C system()函数返回值的含义,所以Python函数的返回值是系统相关的。

这是否说明了这种行为? 帮我澄清一下。

注意:我已经在上述所有步骤之前运行了ulimit -c unlimited。预期结果应为非零或 139(具体而言)。

编辑:我在想这是否有限制!

谢谢!

【问题讨论】:

  • 零被打印了两次,因为 shell 中的echo $? 回显了零,然后 Python REPL 打印了os.system() 的返回值,这是echo 命令的返回码。跨度>
  • 给新手的建议:如果一个答案解决了您的问题,请点击旁边的大复选标记 (✓) 接受它,也可以选择投票(投票至少需要 15 个声望)点)。如果您发现其他答案有帮助,请给他们投票。接受和投票有助于未来的读者。请看【相关帮助中心文章】[1] [1]:stackoverflow.com/help/someone-answers
  • @Allan,感谢您的建议。 :) 如果我想出的答案与后来有人发布相同答案的答案相同呢?

标签: python-3.x shell subprocess exit


【解决方案1】:

我为上述问题编写了以下代码并按预期工作。我使用subprocess.Popen() 方法来实现我的要求。我使用sample.returncode 来获取shell 的退出状态。

def run_cmd():
    ret = 0
    sample_cmd = "./a.out"
    sample = subprocess.Popen(sample_cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out_stdout, out_stderr = sample.communicate()
    if sample.returncode != 0:
        print ("OUTPUT: %s\nERROR: %s\n"%(out_stdout, out_stderr))
        print ("Command:  %s  \nStatus: FAIL "%(sample_cmd))
        sys.stdout.flush()
        if sample.returncode == 139:
            print('Segmentation fauilt(core dumped) occured...with status: ', sample.returncode)
            ret = sample.returncode
        else:
            ret = 1
    else:
        print ("OUTPUT: %s\n"%(out_stdout))             
        print ("Command:  %s  \nStatus: PASS "%(sample_cmd))
        ret = 0

【讨论】:

    【解决方案2】:

    不,您不需要执行echo $?。不会有用的。程序的退出状态是函数os.system的返回值。这就是35584 的号码。 documentation os os.system 告诉你阅读 documentation of os.wait 解释

    一个16位的数字,低字节是杀死进程的信号号,高字节是退出状态(如果信号号为零);如果生成了核心文件,则设置低字节的高位。

    但是,请注意,根据 shell,使用os.system('./a.out'),您可能会获得a.out 的退出状态或 shell 本身的退出状态。通常没有区别,因为 shell 的退出状态是它执行的最后一个命令的退出状态。但是,如果命令因信号而死,则存在差异。 shell 不会用相同的信号杀死自己,它会返回一个对信号进行编码的状态。在大多数 shell 中,这是 128 + signal_number。例如,如果程序死于信号 11(Linux 上的 segfault)并留下核心转储,那么wait 返回的状态为 11。但如果中间有一个 shell,那么 shell 将正常退出代码 128+11。这就是您所看到的:35584 是 (128 + 11) << 8

    为避免这种复杂情况,请使用 subprocess.call 或其变体之一(如果您不需要代码来运行 Python subprocess.run)。

    returncode = subprocess.call(['./a.out'], shell=False).returncode
    if returncode & 0xff == 0:
        exit_code = returncode >> 8
        print('The program exited normally with status {}.'.format(exit_code))
    else:
        print('The program was killed by signal {}.'.format(returncode))
    

    如果你运行os.system('echo $?'),这会启动一个新的shell。您在该 shell 中打印 $? 的初始值,在它运行任何命令之前,$? 在 shell 中的初始值为 0。

    您会在交互环境中看到两次0,因为第一个是echo 命令打印的,第二个是 Python 表达式的值。比较os.system('echo hello')

    请注意,使用os.system,您无法访问命令的输出,因此如果使用echo 打印某些内容,则无法在程序中使用它。为此,您必须使用 subprocess module 中的函数,但仅当您需要 ./a.out 的输出时才需要此函数,而不是获取其退出状态。

    【讨论】:

    • 谢谢!获得如此详尽的信息。阅读所有答案后,我使用subprocess 在上面发布之前编写了相同的代码。但我在下面看不到这些答案。好像被删了!伤心! :(
    【解决方案3】:

    运行时:

    >>> os.system('echo $?')
    0
    0
    

    如果您之前的命令成功,第一个0 将由echo $? 打印,另一个将是刚刚成功的echo $? 调用的返回码,因此您将打印另一个0 .

    你执行的脚本/命令的返回码会直接通过os.system函数返回给你的python程序,所以你不需要使用echo $?

    示例:

    $ more return_code*
    ::::::::::::::
    return_code1.py
    ::::::::::::::
    import os
    
    print os.system('sleep 1')
    #will print 0 after 1sec
    ::::::::::::::
    return_code2.py
    ::::::::::::::
    import os
    
    print os.system('ls abcdef')
    #will print a rc!=0 if the file abcdef is not present in your working directory
    

    处决:

    $ python return_code1.py 
    0
    

    $ python return_code2.py                                                                                                                                                                                                                                        
    ls: cannot access 'abcdef': No such file or directory
    512
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 2022-11-10
      • 2021-01-16
      相关资源
      最近更新 更多