Add errRun to run a command with stderr, stdout, return code and monitoring.
This commit is contained in:
+52
-5
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from resource import setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
|
from resource import setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
|
||||||
import select
|
from select import poll, POLLIN
|
||||||
|
from os import read
|
||||||
from subprocess import call, check_call, Popen, PIPE, STDOUT
|
from subprocess import call, check_call, Popen, PIPE, STDOUT
|
||||||
|
from mininet.log import output, error
|
||||||
from mininet.log import error
|
|
||||||
|
|
||||||
# Command execution support
|
# Command execution support
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ def checkRun( cmd ):
|
|||||||
# pylint doesn't understand explicit type checking
|
# pylint doesn't understand explicit type checking
|
||||||
# pylint: disable-msg=E1103
|
# pylint: disable-msg=E1103
|
||||||
|
|
||||||
def quietRun( *cmd ):
|
def oldQuietRun( *cmd ):
|
||||||
"""Run a command, routing stderr to stdout, and return the output.
|
"""Run a command, routing stderr to stdout, and return the output.
|
||||||
cmd: list of command params"""
|
cmd: list of command params"""
|
||||||
if len( cmd ) == 1:
|
if len( cmd ) == 1:
|
||||||
@@ -34,7 +34,7 @@ def quietRun( *cmd ):
|
|||||||
# select(), which can't handle
|
# select(), which can't handle
|
||||||
# high file descriptor numbers! poll() can, however.
|
# high file descriptor numbers! poll() can, however.
|
||||||
output = ''
|
output = ''
|
||||||
readable = select.poll()
|
readable = poll()
|
||||||
readable.register( popen.stdout )
|
readable.register( popen.stdout )
|
||||||
while True:
|
while True:
|
||||||
while readable.poll():
|
while readable.poll():
|
||||||
@@ -47,6 +47,53 @@ def quietRun( *cmd ):
|
|||||||
break
|
break
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
# This is a bit complicated, but it enables us to
|
||||||
|
# monitor commount output as it is happening
|
||||||
|
|
||||||
|
def errRun( *cmd, **kwargs ):
|
||||||
|
"""Run a command and return stdout, stderr and return code
|
||||||
|
cmd: string or list of command and args
|
||||||
|
stderr: STDOUT to merge stderr with stdout
|
||||||
|
shell: run command using shell
|
||||||
|
echo: monitor output to console"""
|
||||||
|
# Allow passing in a list or a string
|
||||||
|
if len( cmd ) == 1:
|
||||||
|
cmd = cmd[ 0 ]
|
||||||
|
if isinstance( cmd, str ):
|
||||||
|
cmd = cmd.split( ' ' )
|
||||||
|
# By default we separate stderr, don't run in a shell, and don't echo
|
||||||
|
stderr = kwargs.get( 'stderr', PIPE )
|
||||||
|
shell = kwargs.get( 'shell', False )
|
||||||
|
echo = kwargs.get( 'echo', False )
|
||||||
|
popen = Popen( cmd, stdout=PIPE, stderr=stderr, shell=shell )
|
||||||
|
# We use poll() because select() doesn't work with large fd numbers
|
||||||
|
out, err = '', ''
|
||||||
|
poller = poll()
|
||||||
|
poller.register( popen.stdout, POLLIN )
|
||||||
|
fdtofile = { popen.stdout.fileno(): popen.stdout }
|
||||||
|
if popen.stderr:
|
||||||
|
fdtofile[ popen.stderr.fileno() ] = popen.stderr
|
||||||
|
poller.register( popen.stderr, POLLIN )
|
||||||
|
while True:
|
||||||
|
readable = poller.poll()
|
||||||
|
for fd, event in readable:
|
||||||
|
f = fdtofile[ fd ]
|
||||||
|
data = f.read( 1024 )
|
||||||
|
if echo:
|
||||||
|
output( data )
|
||||||
|
if f == popen.stdout:
|
||||||
|
out += data
|
||||||
|
elif f == popen.stderr:
|
||||||
|
err += data
|
||||||
|
returncode = popen.poll()
|
||||||
|
if returncode is not None:
|
||||||
|
break
|
||||||
|
return out, err, returncode
|
||||||
|
|
||||||
|
def quietRun( cmd, **kwargs ):
|
||||||
|
"Run a command and return merged stdout and stderr"
|
||||||
|
return errRun( cmd, stderr=STDOUT, **kwargs )[ 0 ]
|
||||||
|
|
||||||
# pylint: enable-msg=E1103
|
# pylint: enable-msg=E1103
|
||||||
# pylint: disable-msg=E1101,W0612
|
# pylint: disable-msg=E1101,W0612
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user