Run a command locally.

    Arguments:
        command: a command to execute.
        abort: If True, a non-zero return code will trigger an exception.
        capture: If True, returns the output of the command.
            If False, returns a subprocess result.
        echo: if True, prints the command before executing it.
        verbose: If True, prints the output of the command.
        stream: If set, stdout/stderr will be redirected to the given stream.
            Ignored if `capture` is True.

def execute(
    command,
    abort=True,
    capture=False,
    verbose=False,
    echo=False,
    stream=None,
):
    """Run a command locally.

    Arguments:
        command: a command to execute.
        abort: If True, a non-zero return code will trigger an exception.
        capture: If True, returns the output of the command.
            If False, returns a subprocess result.
        echo: if True, prints the command before executing it.
        verbose: If True, prints the output of the command.
        stream: If set, stdout/stderr will be redirected to the given stream.
            Ignored if `capture` is True.
    """
    stream = stream or sys.stdout

    if echo:
        out = stream
        out.write(u'$ %s' % command)

    # Capture stdout and stderr in the same stream
    command = u'%s 2>&1' % command

    if verbose:
        out = stream
        err = stream
    else:
        out = subprocess.PIPE
        err = subprocess.PIPE

    process = subprocess.Popen(
        command,
        shell=True,
        stdout=out,
        stderr=err,
    )
    # propagate SIGTERM to all child processes within
    # the process group. this prevents subprocesses from
    # being orphaned when the current process is terminated
    signal.signal(
        signal.SIGTERM,
        make_terminate_handler(process)
    )

    # Wait for the process to complete
    stdout, _ = process.communicate()
    stdout = stdout.strip() if stdout else ''
    if not isinstance(stdout, unicode):
        stdout = stdout.decode('utf-8')

    if abort and process.returncode != 0:
        message = (
            u'Error #%d running "%s"%s' % (
                process.returncode,
                command,
                ':\n====================\n'
                '%s\n'
                '====================\n' % (
                    stdout
                ) if stdout else ''
            )
        )
        raise Exception(message)
    if capture:
        return stdout
    else:
        return process