Fix run_command sometimes stops

This commit is contained in:
Melissa LeBlanc-Williams 2022-11-10 12:43:27 -08:00
parent c6581122fa
commit 0bc10b7dc0

View file

@ -25,6 +25,8 @@ import sys
import os import os
import shutil import shutil
import subprocess import subprocess
import shlex
import fcntl
import platform import platform
import fileinput import fileinput
import re import re
@ -67,75 +69,76 @@ class Shell:
""" """
Run a shell command and show the output as it runs Run a shell command and show the output as it runs
""" """
original_stdout = sys.stdout def non_block_read(output):
original_stderr = sys.stderr fd = output.fileno()
try: fl = fcntl.fcntl(fd, fcntl.F_GETFL)
# pylint: disable=consider-using-with fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
proc = subprocess.Popen( try:
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE return output.read()
) except:
# pylint: enable=consider-using-with return ""
full_output = ""
while True:
output = proc.stdout.readline()
err = proc.stderr.read()
if err and not suppress_message:
self.error(err.decode("utf-8", errors="ignore"))
if len(output) == 0 and proc.poll() is not None:
break
if output:
decoded_output = output.decode("utf-8", errors="ignore").strip()
if not suppress_message:
self.info(decoded_output)
full_output += decoded_output
except Exception: # pylint: disable=broad-except
pass
finally:
sys.stdout = original_stdout
sys.stderr = original_stderr
if return_output:
return full_output
r = proc.poll()
if r == 0:
return True
return False
def info(self, message): full_output = ""
with subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
) as proc:
while proc.poll() is None:
err = non_block_read(proc.stderr)
if err != "" and not suppress_message:
self.error(err.strip(), end="\n\r")
output = non_block_read(proc.stdout)
if output != "" and not suppress_message:
self.info(output.strip(), end="\n\r")
full_output += output
return_code = proc.poll()
proc.stdout.close()
proc.stderr.close()
if return_output:
return full_output
if return_code:
return False
return True
def info(self, message, **kwargs):
""" """
Display a message with the group in green Display a message with the group in green
""" """
if self._group is not None: if self._group is not None:
print(colored.green(self._group) + " " + message) print(colored.green(self._group) + " " + message, **kwargs)
else: else:
print(message) print(message, **kwargs)
def warn(self, message): def warn(self, message, **kwargs):
""" """
Display a message with the group in yellow Display a message with the group in yellow
""" """
if self._group is not None: if self._group is not None:
print(colored.yellow(self._group) + " " + message) print(colored.yellow(self._group) + " " + message, **kwargs)
else: else:
print(message) print(message, **kwargs)
def bail(self, message=None): def bail(self, message=None, **kwargs):
""" """
Exit and display an error message if given Exit and display an error message if given
""" """
if message is None: if message is None:
self.error("Exiting due to error") self.error("Exiting due to error", **kwargs)
else: else:
self.error(f"Exiting due to error: {message}") self.error(f"Exiting due to error: {message}", **kwargs)
sys.exit(1) sys.exit(1)
def error(self, message): def error(self, message, **kwargs):
""" """
Display some inforrmation Display some information
""" """
if self._group is not None: if self._group is not None:
print(colored.red(self._group) + " " + message) print(colored.red(self._group) + " " + message, **kwargs)
else: else:
print(message) print(message, **kwargs)
@staticmethod @staticmethod
def print_colored(message, color): def print_colored(message, color):