blob: eef5a7694282f87d6a5b0a22f1087f0dea1147c4 [file] [log] [blame]
"""Shell command runner function."""
# Copyright (c) 2020-2022, ARM Limited.
# SPDX-License-Identifier: Apache-2.0
import shlex
import subprocess
class RunShCommandError(Exception):
"""Exception raised for errors running the shell command.
Attributes:
return_code - non-zero return code from running command
full_cmd_esc - command and arguments list (pre-escaped)
stderr - (optional) - standard error output
"""
def __init__(self, return_code, full_cmd_esc, stderr=None, stdout=None):
"""Initialize run shell command error."""
self.return_code = return_code
self.full_cmd_esc = full_cmd_esc
self.stderr = stderr
self.stdout = stdout
self.message = "Error {} running command: {}".format(
self.return_code, " ".join(self.full_cmd_esc)
)
if stdout:
self.message = "{}\n{}".format(self.message, self.stdout)
if stderr:
self.message = "{}\n{}".format(self.message, self.stderr)
super().__init__(self.message)
def run_sh_command(full_cmd, verbose=False, capture_output=False):
"""Run an external shell command.
full_cmd: array containing shell command and its arguments
verbose: optional flag that enables verbose output
capture_output: optional flag to return captured stdout/stderr
"""
# Quote the command line for printing
full_cmd_esc = [shlex.quote(x) for x in full_cmd]
if verbose:
print("### Running {}".format(" ".join(full_cmd_esc)))
if capture_output:
rc = subprocess.run(full_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout = rc.stdout.decode("utf-8")
stderr = rc.stderr.decode("utf-8")
if verbose:
if stdout:
print(stdout, end="")
if stderr:
print(stderr, end="")
else:
stdout, stderr = None, None
rc = subprocess.run(full_cmd)
if rc.returncode != 0:
raise RunShCommandError(rc.returncode, full_cmd_esc, stderr, stdout)
return (stdout, stderr)