"Segmentation fault"
message might be generated by a shell. To find out, whether the process is kill by SIGSEGV
, check proc.returncode == -signal.SIGSEGV
.
If you want to see the message, you could run the command in the shell:
#!/usr/bin/env python
from subprocess import Popen, PIPE
proc = Popen(shell_command, shell=True, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
print out, err, proc.returncode
I've tested it with shell_command="python -c 'from ctypes import *; memset(0,1,1)'"
that causes segfault and the message is captured in err
.
If the message is printed directly to the terminal then you could use pexpect
module to capture it:
#!/usr/bin/env python
from pipes import quote
from pexpect import run # $ pip install pexpect
out, returncode = run("sh -c " + quote(shell_command), withexitstatus=1)
signal = returncode - 128 # 128+n
print out, signal
Or using pty
stdlib module directly:
#!/usr/bin/env python
import os
import pty
from select import select
from subprocess import Popen, STDOUT
# use pseudo-tty to capture output printed directly to the terminal
master_fd, slave_fd = pty.openpty()
p = Popen(shell_command, shell=True, stdin=slave_fd, stdout=slave_fd,
stderr=STDOUT, close_fds=True)
buf = []
while True:
if select([master_fd], [], [], 0.04)[0]: # has something to read
data = os.read(master_fd, 1 << 20)
if data:
buf.append(data)
else: # EOF
break
elif p.poll() is not None: # process is done
assert not select([master_fd], [], [], 0)[0] # nothing to read
break
os.close(slave_fd)
os.close(master_fd)
print "".join(buf), p.returncode-128