Git clone: Redirect stderr to stdout but keep errors being written to stderr

前端 未结 7 604
广开言路
广开言路 2020-11-27 21:11

git clone writes its output to stderr as documented here. I can redirect this with the following command:

git clone https://myrepo          


        
7条回答
  •  时光说笑
    2020-11-27 21:19

    Generally speaking:

    • Console (terminal) applications - whether on Windows or on Unix-like platforms - only have two output streams at their disposal:

      • stdout (standard output) - this is where data ("return values") goes.
      • stderr (standard error) - this is where error messages and - for lack of additional streams - anythings else that isn't data goes, such as progress and status information.
    • Therefore, you cannot and shouldn't infer success vs. failure from the presence of stderr output.

      • Instead, you must rely solely on an application's process exit code:

        • 0 indicates success
        • any nonzero value indicates failure
      • In PowerShell, the **process exit code is reflected in automatic variable $LASTEXITCODE**.


    Specifically, this means:

    • Given git's stderr output lines, you cannot infer whether they represent error message or other kind of non-data information, such as progress or status messages, which git frequently uses.

      • Telling git to categorically redirect its stderr output to stdout (by setting environment variable GIT_REDIRECT_STDERR to string 2>&1; $env:GIT_REDIRECT_STDERR = '2>&1' in PowerShell) does not help, because error messages and progress/status messages alike are then sent there.
    • As stated, you should only infer failure from a nonzero exit code.


    A pragmatic approach is to do the following:

    # Invoke git and capture both its stdout and stderr streams.
    $result = git clone https://myrepo c:\repo 2>&1
    # Throw an error, if git indicated failure.
    if ($LASTEXITCODE) { Throw "git failed (exit code: $LASTEXITCODE):`n$($result -join "`n")" }                                            #`
    # Output the captured result, as an array of strings
    $result | % ToString 
    

    Note:

    • | % ToString ensures that only strings are output, given that the stderr lines (via stream 2) redirected to (>) the success output stream (&1) are wrapped in System.Management.Automation.ErrorRecord instances.

    • 2>&1 can have unexpected side effects - see this answer for background information.

    • Better integration of external-program calls into PowerShell's error handling is the subject of this RFC draft, notably to have the option to abort execution automatically on encountering a nonzero exit code.

提交回复
热议问题