从PowerShell脚本中提取时出错 [英] Error when pulling from PowerShell script

查看:89
本文介绍了从PowerShell脚本中提取时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的PowerShell脚本,可以使文件夹与其git存储库保持最新.

Param(
    [Parameter(Mandatory = $true)][string]$branch,
    [string]$location,
    [int]$depth
)

Get-ChildItem -Recurse -Directory -Depth $depth -Filter _$branch -Name -Path $location | 
ForEach-Object {
    Write-Output "`n$("{0:MM/dd/yy} {0:HH:mm:ss}" -f (Get-Date)): Getting latest from $location$_"
    git -C $location$_ pull
} *>> logs\$branch.log

当存储库是最新的时,它可以正常工作.但是,如果不是,则为输出:

07/29/19 14:47:27: Getting latest from somepath
git : From https://gitlab.com/someplace
At someplace\UpdateBranch.ps1:10 char:5
+     git -C $location$_ pull
+     ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (From https://gi...n/somerepo:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

   b34e5d0..3ec9561  develop           -> origin/develop
   b6d33b1..65fb520  feature/feature1  -> origin/feature/feature1
 * [new branch]      feature/feature2  -> origin/feature/feature2
   c3fe1c9..9553b72  master            -> origin/master

Updating b34e5d0..3ec9561
Fast-forward
 stylesheet.scss      | 4 ++--
 ...
 6 files changed, 11 insertions(+), 10 deletions(-)

似乎可以进行更新,但也会输出错误.

解决方案

Git将更详细的数据写入Error流,以允许解析器解析最重要的位.然后,这些解析器可以忽略针对人类用户的更为冗长的输出.该数据通过stderr流发送. Powershell默认将stderr上的数据转换为错误记录,并抛出您看到的错误.

以下 github问题有很多可能的解决方案. /p>

似乎最简单的方法是添加--porcelain --quiet,它们不会写将详细数据复制到stderr或完全没有数据.

git checkout branch --porcelain
git checkout branch --quiet

另一种选择是在整个环境中为git配置标准重定向模式,至少这样,您无需将重定向分散到整个代码中:

$env:GIT_REDIRECT_STDERR = '2>&1'

中可以找到更多选项这个StackOverflow答案,将所有重定向的消息强制为其字符串表示形式也可以很好地工作:

git checkout branch 2>&1 | %{ "$_" }

另一种语法是:

"$(git checkout branch ? 2>&1 )"

另一种解决方法是通过cmd调用git:

& cmd /c 'git checkout branch 2>&1'

在这个答案中您将找到一个包装函数,以一种干净的方式调用git .

function Invoke-Git {
<#
.Synopsis
Wrapper function that deals with Powershell's peculiar error output when Git uses the error stream.

.Example
Invoke-Git ThrowError
$LASTEXITCODE

#>
    [CmdletBinding()]
    param(
        [parameter(ValueFromRemainingArguments=$true)]
        [string[]]$Arguments
    )

    & {
        [CmdletBinding()]
        param(
            [parameter(ValueFromRemainingArguments=$true)]
            [string[]]$InnerArgs
        )
        C:\Full\Path\To\git.exe $InnerArgs
    } -ErrorAction SilentlyContinue -ErrorVariable fail @Arguments

    if ($fail) {
        $fail.Exception
    }

}

# Could shorten the function name. I instead alias it, for terseness.
Set-Alias -Name git -Value Invoke-Git

# Also alias the name with the extension, as it is called by some applications this way.
Set-Alias -Name git.exe -Value Invoke-Git

I have a simple PowerShell script to keep a folder up-to-date with its git repository.

Param(
    [Parameter(Mandatory = $true)][string]$branch,
    [string]$location,
    [int]$depth
)

Get-ChildItem -Recurse -Directory -Depth $depth -Filter _$branch -Name -Path $location | 
ForEach-Object {
    Write-Output "`n$("{0:MM/dd/yy} {0:HH:mm:ss}" -f (Get-Date)): Getting latest from $location$_"
    git -C $location$_ pull
} *>> logs\$branch.log

It works fine when the repository is already up-to-date. However, when it isn't, this is the output:

07/29/19 14:47:27: Getting latest from somepath
git : From https://gitlab.com/someplace
At someplace\UpdateBranch.ps1:10 char:5
+     git -C $location$_ pull
+     ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (From https://gi...n/somerepo:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

   b34e5d0..3ec9561  develop           -> origin/develop
   b6d33b1..65fb520  feature/feature1  -> origin/feature/feature1
 * [new branch]      feature/feature2  -> origin/feature/feature2
   c3fe1c9..9553b72  master            -> origin/master

Updating b34e5d0..3ec9561
Fast-forward
 stylesheet.scss      | 4 ++--
 ...
 6 files changed, 11 insertions(+), 10 deletions(-)

It seems to do the update but also outputs an error.

解决方案

Git writes the more verbose data to the Error stream to allow parsers to parse the most important bits. These parsers can then ignore the more verbose output that's meant for the human user. That data is sent through the stderr stream. Powershell converts data on stderr to an error record by default, throwing the error you see.

The following github issue has a whole bunch of possible solutions.

The one that seems to be the simplest is to add --porcelain or --quiet, which will not write verbose data to stderr or no data at all.

git checkout branch --porcelain
git checkout branch --quiet

Another option is to configure the standard redirect mode for git through the environment, at least this way you don't need to scatter the redirect throughout the whole code:

$env:GIT_REDIRECT_STDERR = '2>&1'

More options are found in this StackOverflow answer, forcing all redirected messages to their string representation works nicely too:

git checkout branch 2>&1 | %{ "$_" }

An alternate syntax for that is:

"$(git checkout branch ? 2>&1 )"

Another workaround is to invoke git through cmd:

& cmd /c 'git checkout branch 2>&1'

And in this answer you'll find a wrapper function to call git in a clean manner.

function Invoke-Git {
<#
.Synopsis
Wrapper function that deals with Powershell's peculiar error output when Git uses the error stream.

.Example
Invoke-Git ThrowError
$LASTEXITCODE

#>
    [CmdletBinding()]
    param(
        [parameter(ValueFromRemainingArguments=$true)]
        [string[]]$Arguments
    )

    & {
        [CmdletBinding()]
        param(
            [parameter(ValueFromRemainingArguments=$true)]
            [string[]]$InnerArgs
        )
        C:\Full\Path\To\git.exe $InnerArgs
    } -ErrorAction SilentlyContinue -ErrorVariable fail @Arguments

    if ($fail) {
        $fail.Exception
    }

}

# Could shorten the function name. I instead alias it, for terseness.
Set-Alias -Name git -Value Invoke-Git

# Also alias the name with the extension, as it is called by some applications this way.
Set-Alias -Name git.exe -Value Invoke-Git

这篇关于从PowerShell脚本中提取时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆