【问题标题】:PowerShell Transcript is not capturing git outputPowerShell 脚本未捕获 git 输出
【发布时间】:2019-11-19 21:01:16
【问题描述】:

我正在编写一个将执行一些 git 操作的脚本,我想使用 Start-Transcript 来监控它。然而,成绩单缺少大部分 git 输出。

我尝试将git 输出通过管道传输到Out-HostOut-Default,但都不起作用。

这是我的代码...

$DateTime = Get-Date -Format "yyyyMMdd_HHmmss"
$TranscriptName = "PSTranscript_$DateTime"

Start-Transcript -Path ".\$TranscriptName.txt"

git --bare clone <GIT_REPO_URL> repo | Out-Default

Stop-Transcript

这是我的控制台输出...

Transcript started, output file is .\PSTranscript_20191119_155424.txt
Cloning into 'repo'...
remote: Counting objects: 58975, done.
remote: Compressing objects: 100% (21457/21457), done.
remote: Total 58975 (delta 43348), reused 51727 (delta 37145)
Receiving objects: 100% (58975/58975), 70.46 MiB | 3.95 MiB/s, done.
Resolving deltas: 100% (43348/43348), done.
Checking out files: 100% (3878/3878), done.
Transcript stopped, output file is .\PSTranscript_20191119_155424.txt

这是记录中捕获的内容,请注意,git 的某些输出丢失了

**********************
Windows PowerShell transcript start
Start time: 20191119155424
Username: 
RunAs User: 
Configuration Name: 
Machine: 
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 20644
PSVersion: 5.1.17134.858
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17134.858
BuildVersion: 10.0.17134.858
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is .\PSTranscript_20191119_155424.txt
**********************
Windows PowerShell transcript end
End time: 20191119155457
**********************

【问题讨论】:

  • stackoverflow.com/a/47367768/6309 可能会有所帮助。
  • Start-Transcript 应该捕获所有内容,而不管输出流如何。但是,似乎将 git 命令输出传送到 Out-Default 会导致输出未记录在脚本中。]
  • 我已经修改了我的答案,以反映以下结论:Out-Default 应该永远直接从用户代码中调用,基于 this discussion on GitHub

标签: git powershell


【解决方案1】:

没有理由调用Out-Default - 只需按原样使用git 命令,您的问题就会消失:它的stdout 和stderr 流都将被转录。

git 默认将 status 信息写入 stderr,并且 - 错误 - 使用 Out-Default 具体会影响 stderr 输出,如底部。

以下示例演示了来自外部程序的 stdout 和 stderr 输出都被捕获在脚本中

$file = [IO.Path]::GetTempFileName()

"--- DIRECT OUTPUT ---`n"

Start-Transcript $file

# Execute a command that produces
# both stdout and stderr output.
# Do NOT use Out-Default.
if ($env:OS -eq 'Windows_NT') {  # Windows
  cmd /c 'echo hi & nosuch'
} else {                         # macOS, Linux
  sh -c 'echo hi; nosuch'
}

Stop-Transcript

"`n--- CORE CONTENT OF TRANSCRIPT ---"

# Print the core of the transcript.
((Get-Content -Raw $file) -split '(?m)^\*+\s*$')[2]

Remove-Item $file

在 Windows 上,您会看到类似以下内容,表明两个流都已被捕获:

--- DIRECT OUTPUT ---

Transcript started, output file is C:\Users\jdoe\AppData\Local\Temp\tmp342C.tmp
hi
'nosuch' is not recognized as an internal or external command,
operable program or batch file.
Transcript stopped, output file is C:\Users\jdoe\AppData\Local\Temp\tmp342C.tmp

--- CORE CONTENT OF TRANSCRIPT ---

Transcript started, output file is C:\Users\jdoe\AppData\Local\Temp\tmp342C.tmp
hi
'nosuch' is not recognized as an internal or external command,
operable program or batch file.

Out-Default cmdlet 的用途:

Out-Default 不是要从用户代码中调用。

相反,它仅供PowerShell host applications 使用,包括PowerShell 本身。 它使用PowerShell's output-formatting system 创建输出对象的漂亮打印字符串表示,并将它们发送到主机进行显示。

它是公共 cmdlet 的原因是您可以覆盖它以定义 自定义 输出格式化程序,尽管这样做很少见。

覆盖就像在会话中定义高级Out-Default 函数一样简单,该函数必须具有相同的参数声明和管道绑定行为。您可以通过包装器(代理)函数来构建这样的函数,如this answer 的底部部分所示)。请注意,为了从您的函数中生成可见的输出,您必须将自定义格式的字符串发送到原始 Out-Default 或使用 主机 API 来打印它们(Write-Host,最简单的案例)。


错误:

您对Out-Default 的使用——尽管不明智——可以说仍然有效。

虽然这对于Out-Default 来说是一个有争议的问题,但鉴于不应直接调用它,Out-Host 会出现同样的问题(从 PowerShell Core 7.0.0-preview.6 开始),并且 是调用Out-Host 的正当理由,即仅显式打印到显示器(这样做不应影响转录行为)。

具体来说,如果您明确使用Out-Host,来自外部程序stderr输出意外地不会记录在脚本中。 (相比之下,PowerShell 命令不会出现问题。)

问题已在GitHub issue #11134报告。

【讨论】:

    【解决方案2】:

    编辑:我在原始代码中留下Out-Default 是个错误。这遇到了Out-Default 中的一个错误,该错误专门影响stderr。删除 Out-Default 导致修复了我的脚本,现在它成功地转录了 git 输出。


    @VonC 发布了一个非常有帮助的 link,它为我指明了正确的方向!

    只需将值为2&gt;&amp;1GIT_REDIRECT_STDERR 环境变量添加到Windows 用户环境变量中即可。

    如果您使用的是 Windows,这里有一个漂亮的 PowerShell 命令,您可以运行它来添加环境变量。

    [System.Environment]::SetEnvironmentVariable("GIT_REDIRECT_STDERR", "2>&1", "User")
    

    下面是我的新成绩单的样子...

    **********************
    Windows PowerShell transcript start
    Start time: 20191119165056
    Username: 
    RunAs User: 
    Configuration Name: 
    Machine: 
    Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    Process ID: 16440
    PSVersion: 5.1.17134.858
    PSEdition: Desktop
    PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17134.858
    BuildVersion: 10.0.17134.858
    CLRVersion: 4.0.30319.42000
    WSManStackVersion: 3.0
    PSRemotingProtocolVersion: 2.3
    SerializationVersion: 1.1.0.1
    **********************
    Transcript started, output file is .\PSTranscript_20191119_165056.txt
    Cloning into bare repository 'repo'...
    remote: Counting objects: 58975, done.
    remote: Compressing objects: 100% (21457/21457), done.
    remote: Total 58975 (delta 43347), reused 51727 (delta 37145)
    Receiving objects: 100% (58975/58975), 70.33 MiB | 6.04 MiB/s, done.
    Resolving deltas: 100% (43347/43347), done.
    **********************
    Windows PowerShell transcript end
    End time: 20191119165115
    **********************
    

    【讨论】:

    • 谢谢!对于我的环境,我必须使用这一行,它应该是功能等效的: $env:GIT_REDIRECT_STDERR = "2>&1"
    【解决方案3】:

    Start-Transcript 应该捕获写入控制台主机的所有内容,无论它写入哪个流。但是,我确实注意到,当我将一个 git 命令传送到 Out-Default 时,我没有将任何内容写入该命令的脚本,即使它显示在控制台上也是如此。

    我无法解释为什么会发生这种情况,但请从您的克隆命令中删除 | Out-Default,它应该将输出记录到脚本中。

    【讨论】:

    • 感谢您的完整性检查,我正在阅读并期待 Out-Default 能够解决问题,但遇到了同样的事情。但是,似乎重定向输出确实可以解决问题。
    • 这绝对会让我发疯。我的工作站上没有那个设置,我仍然将git 输出记录到成绩单,除非我将它传送到Out-Default。我想这可能是使用 ConEmu 作为我的控制台主机的一个怪癖,但即使使用普通的 powershell.exe 我也会得到相同的行为。
    • 好点。请注意,它是来自外部程序的 stderr 输出,具体来说,它没有被记录下来,但主要的一点是确实没有理由一开始就使用 Out-Default
    • 我已经修改了我的答案,以反映基于this discussion on GitHub 不应该永远直接从用户代码中调用Out-Default 的结论。虽然 Out-Default 行为因此是一个有争议的问题,但同样的问题(省略了脚本中的 stderr 输出)也会影响Out-Host,并且Out-Host 确实有合法用途。
    猜你喜欢
    • 2018-05-01
    • 2018-06-09
    • 1970-01-01
    • 2018-05-04
    • 2016-07-07
    • 2018-04-27
    • 2020-02-03
    • 1970-01-01
    • 2012-05-10
    相关资源
    最近更新 更多