I would like to execute system calls from my (python) script such that the output of the sys-call is generated on the terminal where script is running as well as is captured in a logfile. However I am not able to make this work for interactive system calls.
I started with following code that does not capture the system call in a logfile, but works correctly (as in is able to display output on terminal, and can take inputs I type in terminal) for both basic commands such as system('echo HEYA')
as well as interactive commands such as system('python')
:
def system(cmd):
log.info(f"Running: {cmd}")
try:
subprocess.run(cmd, check=True, shell=True, executable=SHELL)
except subprocess.CalledProcessError as err:
log.error(err.output)
Notes: log
is a logger (created using standard logging
module). SHELL
variable holds a shell of my choice.
Now, I modify the above to be able to redirect the process output to terminal as well as logfile on disk in realtime with following code:
def system(cmd):
log.info(f"Running: {cmd}")
try:
process = subprocess.Popen(cmd,
shell=True, executable=SHELL, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
o = process.stdout.readline().rstrip('\n')
if o == '' and process.poll() is not None:
break
if o:
syslog.info(o)
ret = process.poll()
if ret:
log.error(f"Failed with exit code: {ret}")
else:
log.info("Done")
except:
err = sys.exc_info()[0]
log.error(err)
raise
Notice that I use a different logger (syslog
) to redirect outputs to logfile and terminal. The only reason for this, is I want system command outputs formatted differently from other messages generated in the script.
The second version of system
function works for something like system('echo HEYA')
but not for interactive calls like system('python')
. Any suggestions what I may be doing wrong, and how I can get this to work?