깃 클론:stdout으로 stderr 리디렉션하지만 오류는 stderr에 계속 기록됩니다.
git clone을 출을에씁다에 .stderr여기에 기록된 바와 같이다음 명령을 사용하여 이를 리디렉션할 수 있습니다.
git clone https://myrepo c:\repo 2>&1
그러나 이렇게 하면 오류를 포함한 모든 출력이 리디렉션됩니다.stderrstdout진행률 메시지를 다음으로 리디렉션할 수 있는 방법이 있습니까?stdout하지만 오류 메시지는 여전히 다음에 기록됩니다.stderr.
MingW 업데이트는 Git 2.15.x/2.16(2018년 1분기)을 통해 리디렉션을 처리하는 새로운 방법을 제공합니다.
커밋 b2f5571, 커밋 1a172e4, 커밋 3f94442(2017년 11월 1일)를 요하네스 쉰들린()dscho 참조.
(주니오 C 하마노에 의해 합병 -- -- 2017년 11월 9일 커밋 421f21c에서)
mingw실험 피쳐를 리디렉션 표준 핸들에 추가특히 Visual Studio의 Team Explorer와 같은 응용 프로그램에서 Git를 호출할 때 stdin/stdout/stderr을 올바르게 닫아야 합니다.
그러나 윈도우즈에서 프로세스를 생성할 때 이러한 핸들을 사용하려면 해당 핸들을 상속 가능한 것으로 표시해야 하지만 이 플래그는 글로벌 플래그이므로 이러한 프로세스를 닫을 수 없는 다른 생성된 프로세스에서 사용할 수 있습니다.
GIT_REDIRECT_STDIN파일 또는 더 나은 명명된 파이프(유닉스 소켓과 유사함)에 대한 경로를 지정하고 생성된 Git 프로세스에서 사용하는 경로를 지정합니다.
이는 위에서 언급한 문제를 해결하는 데 도움이 됩니다. 시작할 때 명명된 파이프가 상속할 수 없는 방식으로 열리며 핸들이 전달되지 않습니다(따라서 상속된 핸들은 생성된 자식이 닫을 필요가 없습니다).이 기능은 v2.11.0(2) 이후에 Git for Windows(실험용으로 표시됨)와 함께 제공되었으므로 그 동안 몇 가지 심각한 테스트가 있었습니다.
이제 Git 설명서에는 다음이 포함됩니다.
GIT_REDIRECT_STDIN:
GIT_REDIRECT_STDOUT:
GIT_REDIRECT_STDERR:
Windows 전용: 표준 입력/출력/오류 핸들을 환경 변수에 의해 지정된 경로로 리디렉션할 수 있습니다.이것은 특히 표준 핸들을 전달하는 표준 방식인 멀티 스레드 애플리케이션에서 유용합니다.
CreateProcess()이는 핸들을 상속 가능한 것으로 표시해야 하기 때문에 옵션이 아닙니다(따라서 생성된 모든 프로세스가 해당 핸들을 상속하므로 일반 Git 작업을 차단할 수 있습니다).을 위해 명명된 주용도통예파사용것는입하니다를이프된명명해위신을는요예▁for것▁the(입:).
\\.\pipe\my-git-stdin-123).
다음과 같은 이점이 있습니다.
mingw을 리디렉션합니다."
2>&1Powershell 및 Unix 쉘의 표기법은 다음을 의미합니다.stderr의 동일한 핸들로 리디렉션됩니다.stdout이미 작성되었습니다.이 특별한 값을 사용하여 다음과 같은 트릭을 허용합니다.
GIT_REDIRECT_STDERR그리고.GIT_REDIRECT_STDOUT이 전의값다이같과으면음자인2>&1,그리고나서stderr와 동일한 핸들에 간단히 기록됩니다.stdout.이 기능은 Jeff Hostetler에 의해 제안되었습니다.
: 사용 예:$env:GIT_REDIRECT_STDERR = '2>&1'
이 스크립트를 사용하여 git 명령을 실행합니다.git는 성공적인 경우에도 stderr에 쓰기 때문에(예: 동기화 시 pull), 이러한 경우를 처리하고 출력의 첫 줄을 기록합니다. 이는 일반적으로 알아야 할 사항입니다.
<#
.Synopsis
Invoke git, handling its quirky stderr that isn't error
.Outputs
Git messages, and lastly the exit code
.Example
Invoke-Git push
.Example
Invoke-Git "add ."
#>
function Invoke-Git
{
param(
[Parameter(Mandatory)]
[string] $Command )
try {
$exit = 0
$path = [System.IO.Path]::GetTempFileName()
Invoke-Expression "git $Command 2> $path"
$exit = $LASTEXITCODE
if ( $exit -gt 0 )
{
Write-Error (Get-Content $path).ToString()
}
else
{
Get-Content $path | Select-Object -First 1
}
$exit
}
catch
{
Write-Host "Error: $_`n$($_.ScriptStackTrace)"
}
finally
{
if ( Test-Path $path )
{
Remove-Item $path
}
}
}
일반적으로 말하면,
콘솔(터미널) 응용 프로그램(Windows 또는 유닉스 계열 플랫폼)에는 두 개의 출력 스트림만 사용할 수 있습니다.
- stdout(표준 출력) - 여기서 데이터("반환 값")가 이동합니다.
- stderr(표준 오류) - 여기서 오류 메시지와 - 추가 스트림이 없는 경우 - 진행률 및 상태 정보와 같이 데이터가 아닌 다른 모든 항목이 표시됩니다.
따라서 stderr 출력의 존재로부터 성공 대 실패를 추론할 수도 없고 추론해서도 안 됩니다.
대신 응용 프로그램의 프로세스 종료 코드에만 의존해야 합니다.
0성공을 나타냄- 0이 아닌 값은 고장을 나타냅니다.
PowerShell에서는 프로세스 종료 코드가 자동 변수에 반영됩니다.
구체적으로, 이는 다음을 의미합니다.
의 stderr 출력 라인이 오류 메시지를 나타내는지 아니면 진행률 또는 상태 메시지와 같은 기타 비데이터 정보를 나타내는지 추론할 수 없습니다.
git빈번히 사용하는- 하말기기▁
git변수 )으로 범주적으로 . stderr stdout은 stdout입니다.GIT_REDIRECT_STDERR끈로묶에 줄을2>&1;$env:GIT_REDIRECT_STDERR = '2>&1'오류 메시지와 진행률/상태 메시지가 마찬가지로 전송되기 때문에 PowerShell)에서는 도움이 되지 않습니다.
- 하말기기▁
설명한 바와 같이 0이 아닌 종료 코드에서만 오류를 추론해야 합니다.
실용적인 접근 방식은 다음과 같습니다.
# Invoke git and capture both its stdout and stderr streams, as strings.
$result = git clone https://myrepo c:\repo 2>&1 | % ToString
# 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 lines.
$result
참고:
| % ToString(%의 줄임말)은 stderr 라인(스트림을 통해)을 고려할 때 문자열만 출력되도록 합니다.2( )로>스트림은 ()입니다.&1)는 인스턴스로 묶입니다.- PowerShell(Core) 7+에서는 결과를 인쇄하려는 경우에만 엄격하게 이 작업이 필요하지 않습니다.
[System.Management.Automation.ErrorRecord]문자열처럼 인쇄합니다. 이와 대조적으로 Windows PowerShell은 문자열이 PowerShell 오류인 것처럼 인쇄합니다.
- PowerShell(Core) 7+에서는 결과를 인쇄하려는 경우에만 엄격하게 이 작업이 필요하지 않습니다.
2>&1PowerShell 7.1 버전에서는 예상치 못한 부작용이 발생할 수 있습니다. 배경 정보는 이 답변을 참조하십시오.외부 프로그램 호출을 PowerShell의 오류 처리에 더 잘 통합하는 것이 이 RFC 초안의 주제이며, 특히 0이 아닌 종료 코드가 발생할 때 자동으로 실행을 중단하는 옵션이 있습니다.
저와 마찬가지로, 만약 당신이 stderr에서 오류와 오류만 발생시키는 것에 더 관심이 있고 어느 쪽이든 진행에 관심이 없다면, 명령에 --quiet(또는 -q)를 추가하면 되는 아주 간단한 해결 방법이 있습니다.
이는 실제 오류가 발생하지 않는 한 진행 상황 보고를 아예 중지하도록 git에 지시합니다.
에서 제거할 수 있습니다.stderr.
다음 명령을 사용합니다.
git clone https://myrepo c:\repo 2>$null
것을 함으로써.stderr표시되지 않습니다.
할 수 할 수 있으며, 은 "" " " " " " 입니다. 명령이 실패하면 모든 출력은stderrstdout
: "git"으로 표시됩니다.stderr명령이 윈도우즈에서만 성공하는 경우에도 마찬가지입니다.t.
필요에 따라 Invoke-Git를 수정했습니다.
제가 해결책을 찾으면서 읽은 많은 게시물에서 저는 많은 사람들이 이것을 사용할 수 있다고 생각합니다.
즐거운 시간 되세요.
다음을 수행할 이 버전:
- 전달된 Git 명령을 실행합니다(Git가 이미 실행 경로에 있다고 가정합니다).
- 모든 것이 잘되면 모든 출력(stdout 및 stderr)이 stderr을 통해가 아니라 호스트에 표시됩니다.
- $LASTEX 확인실제로 오류가 발생했는지 확인하는 ITCODE입니다.오류가 발생한 경우 모든 출력이 호출자에게 전달되어 처리됩니다.
<#
.Synopsis
Invoke git, handling its quirky stderr that isn't error
.Outputs
Git messages
.Example
Invoke-Git push
.Example
Invoke-Git "add ."
#>
function Invoke-Git
{
param(
[Parameter(Mandatory)]
[string] $Command )
try {
# I could do this in the main script just once, but then the caller would have to know to do that
# in every script where they use this function.
$old_env = $env:GIT_REDIRECT_STDERR
$env:GIT_REDIRECT_STDERR = '2>&1'
Write-Host -ForegroundColor Green "`nExecuting: git $Command "
$output = Invoke-Expression "git $Command "
if ( $LASTEXITCODE -gt 0 )
{
# note: No catch below (only the try/finally). Let the caller handle the exception.
Throw "Error Encountered executing: 'git $Command '"
}
else
{
# because $output probably has miultiple lines (array of strings), by piping it to write-host we get multiple lines.
$output | Write-Host
}
}
# note: No catch here. Let the caller handle it.
finally
{
$env:GIT_REDIRECT_STDERR = $old_env
}
}
일부 사람들에게 영감을 줄 수 있는 또 다른 방법이 있습니다.다른 사람들이 지적했듯이 종료 코드를 리디렉션하고 확인하는 것이 잘 작동합니다.다른 답변과 다른 점:
- Git가 실행되는 동안에는 아무 일도 일어나지 않으므로 파일로 리디렉션하는 것은 약간 성가신 일입니다. 출력을 반환하고 별도의 오류 메시지를 사용하십시오.절충안이지만, 저는 그것을 더 좋아합니다.
- Write-Host가 구성 가능하므로 Write-Host 대신 Write-Verbose 사용
- 거친 던지기 대신 쓰기 오류를 사용하여 오류를 생성합니다.ErrorAction, ErrorVariable과 같은 것들이 예상대로 작동하도록 합니다.
- 을 사용하는 것처럼 실행할합니다.
-C디렉토리에 CD를 저장하는 대신 일반적으로 해당 기능이 없는 명령에 대해서도 지원합니다.은 있다니습수를 할 수 .igit -dir some/path stash저는 이것을 주로 디렉토리에 CD를 넣어야 하는 자동화된 스크립트에서 사용합니다. - ValueFromRemainingArguments 등을 사용하면 git 명령을 직접 작성하는 것처럼 전달할 수 있으므로 문자열을 필요로 하지 않고 계속 허용할 수 있습니다.
igit checkout master와 같이 작동합니다.igit 'checkout master'표준 : 거, 즉, 표, 준 PS ▁if)로 문자열이 합니다. 따라서 인용문을 기본 명령으로 전달해야 하는 경우에도 실제 문자열이 필요합니다.igit log'--format=filename%d'. And PS doesn't require you to type full parameter names meaning푸시-비짓 시푸▁- -v.will be interpreted as- 시푸상 - 세보기기▁ig.instead of passing-vi.e. verbose push to git. Use double dash to deal with that결국 igit -- push -v' 씁니다또따를옴는표씁▁ig니다▁after▁push.
코드:
<#
.SYNOPSIS
Run git, Powershell-style.
.DESCRIPTION
By default some git commands (clone, checkout, ...) write a part of their
output to stderr, resulting in PS treating that as an error.
Here we work around that by redirecting stderr and using git's exit code
to check if something was actually wrong, and use Write-Error if that's the case,
i.e. standard PS error handling which works with -ErrorAction/-ErrorVariable etc.
The command can be passed as a string or as separate strings.
Additionally takes a $Directory argument which when used has the same effect as git -C,
but also works for clone/stash/submodule/... commands making it easier to automate those.
The $Git argument can be used to specify the executable.
.EXAMPLE
Invoke-Git status
Invoke-Git -Directory some/path status
Invoke-Git 'push -v'
Invoke-Git -Verbose -- push -v # Pass that last -v to git.
#>
function Invoke-Git {
[CmdletBinding()]
param(
[Parameter()] [Alias('Dir')] [String] $Directory = $null,
[Parameter()] [String] $Git = 'git',
[Parameter(Mandatory, Position=0, ValueFromRemainingArguments=$true)] [string] $Command
)
try {
$commandParts = $Command.Split(' ')
$subCommand = $commandParts[0]
if ($Directory -and $subCommand -eq 'clone') {
# To make all commands look alike handle this one as well.
$Command = ($commandParts + @($Directory)) -join ' '
} elseif ($Directory -and @('submodule', 'stash', 'init') -eq $subCommand) {
# These currently require one to be in the git directory so go there.
$currentDir = Get-Location
cd $Directory
} elseif ($Directory) {
if ($commandParts -eq '-C') {
# Not an error, git will pick the last one, but unexpected.
Write-Warning 'Better use either -Directory or -C, not both'
}
$Command = "-C $Directory " + $Command
}
Write-Verbose "Invoke-Git on '$Directory' with command '$Command'"
$gitRedirection = $env:GIT_REDIRECT_STDERR
$env:GIT_REDIRECT_STDERR = '2>&1'
# Deliberately not getting output here: while this means we cannot pass the actual error to Write-Error,
# it does result in all commands being shown 'live'. Otherwise when doing a clone for instance,
# nothing gets displayed while git is doing it's thing which is unexepected and too different from normal usage.
Invoke-Expression "$Git $Command"
if ($LASTEXITCODE -ne 0) {
Write-Error "git exited with code $LASTEXITCODE"
}
} finally {
$env:GIT_REDIRECT_STDERR = $gitRedirection
if ($currentDir) {
cd $currentDir
}
}
}
New-Alias -Name IGit -Value Invoke-Git -ErrorAction SilentlyContinue
언급URL : https://stackoverflow.com/questions/34820975/git-clone-redirect-stderr-to-stdout-but-keep-errors-being-written-to-stderr
'programing' 카테고리의 다른 글
| 스프링 스케줄링: @스케줄링 대 쿼츠 (0) | 2023.08.04 |
|---|---|
| 타자 스크립트를 사용하여 각도 2에서 장치 디스플레이의 높이와 너비를 얻는 방법은 무엇입니까? (0) | 2023.08.04 |
| 브라우저는 모든 페이지 로드에서 자바스크립트를 구문 분석합니까? (0) | 2023.08.04 |
| iPhone Store Kit "iTunes Store에 연결할 수 없습니다" (0) | 2023.08.04 |
| 개체가 개체 목록에 있는지 확인합니다. (0) | 2023.08.04 |