def run_command()

in azurelinuxagent/common/utils/shellutil.py [0:0]


def run_command(command, input=None, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, log_error=False, encode_input=True, encode_output=True, track_process=True, timeout=None):  # pylint:disable=W0622
    """
        Executes the given command and returns its stdout.

        If there are any errors executing the command it raises a RunCommandException; if 'log_error'
        is True, it also logs details about the error.

        If encode_output is True the stdout is returned as a string, otherwise it is returned as a bytes object.

        If track_process is False the command is not added to list of running commands

        This function is a thin wrapper around Popen/communicate in the subprocess module:
           * The 'input' parameter corresponds to the same parameter in communicate
           * The 'stdin' parameter corresponds to the same parameters in Popen
           * Only one of 'input' and 'stdin' can be specified
           * The 'stdout' and 'stderr' parameters correspond to the same parameters in Popen, except that they
             default to subprocess.PIPE instead of None
           * If the output of the command is redirected using the 'stdout' or 'stderr' parameters (i.e. if the
             value for these parameters is anything other than the default (subprocess.PIPE)), then the corresponding
             values returned by this function or the CommandError exception will be empty strings.

        NOTE: The 'timeout' parameter is ignored on Python 2

        NOTE: This is the preferred method to execute shell commands over `azurelinuxagent.common.utils.shellutil.run` function.
    """
    if input is not None and stdin is not None:
        raise ValueError("The input and stdin arguments are mutually exclusive")

    def command_action():
        popen_stdin = communicate_input = None
        if input is not None:
            popen_stdin = subprocess.PIPE
            communicate_input = input.encode() if encode_input and isinstance(input, str) else input  # communicate() needs an array of bytes
        if stdin is not None:
            popen_stdin = stdin
            communicate_input = None

        if track_process:
            process = _popen(command, stdin=popen_stdin, stdout=stdout, stderr=stderr, shell=False)
        else:
            process = subprocess.Popen(command, stdin=popen_stdin, stdout=stdout, stderr=stderr, shell=False)

        try:
            if sys.version_info[0] == 2:  # communicate() doesn't support timeout on Python 2
                command_stdout, command_stderr = process.communicate(input=communicate_input)
            else:
                command_stdout, command_stderr = process.communicate(input=communicate_input, timeout=timeout)
        except TimeoutExpired:
            if log_error:
                logger.error(u"Command [{0}] timed out", __format_command(command))

            command_stdout, command_stderr = '', ''

            try:
                process.kill()
                # try to get any output from the command, but ignore any errors if we can't
                try:
                    command_stdout, command_stderr = process.communicate()
                # W0702: No exception type(s) specified (bare-except)
                except:  # pylint: disable=W0702
                    pass
            except Exception as exception:
                if log_error:
                    logger.error(u"Can't terminate timed out process: {0}", ustr(exception))
            raise CommandError(command=__format_command(command), return_code=-1, stdout=command_stdout, stderr="command timeout\n{0}".format(command_stderr))

        if track_process:
            _on_command_completed(process.pid)

        return process.returncode, command_stdout, command_stderr

    return __run_command(command_action=command_action, command=command, log_error=log_error, encode_output=encode_output)