退出状态$?在发生分段故障时使用python

时间:2018-06-18 06:04:35

标签: python-3.x shell subprocess exit

我需要使用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系统()函数的返回值的含义,因此Python函数的返回值是依赖于系统的。

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

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

编辑:我在想是否存在限制!

谢谢!

3 个答案:

答案 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不会使用相同的信号自杀,它将返回编码信号的状态。在大多数贝壳中,128 + signal_number。例如,如果程序死于信号11(Linux上的段错误)并留下核心转储,那么wait返回的状态为11.但是如果它们之间存在shell,那么shell将会通常使用退出代码128 + 11退出。这就是你所看到的:35584是(128 + 11) << 8

要避免这种复杂情况,请使用subprocess.call或其中一种变体(如果您不需要代码来运行Python&lt; = 3.4),则可以使用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的输出时才需要此功能,而不是为了获得退出状态。

答案 1 :(得分:1)

运行时:

>>> 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

答案 2 :(得分:0)

我为上述问题编写了以下代码,并按预期工作。我使用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