source

PowerShell의 표준 오류에 쓰는 방법은 무엇입니까?

factcode 2023. 7. 28. 22:58
반응형

PowerShell의 표준 오류에 쓰는 방법은 무엇입니까?

표준 오류 스트림에 에코하는 방법과 실행 파일의 오류 스트림을 리디렉션하는 방법을 모두 파악하는 데 어려움을 겪고 있습니다.

저는 본 셸과 셸 배경에서 왔습니다. 제가 사용할 것입니다.

# Write to stderr
echo "Error Message!" >&2

# Redirect stderr to file
/do/error 2>/tmp/err.msg

사용하다Write-Errorstderr에 글을 . stderr 을로파다면사음용다니합을려를 합니다.

 Write-Error "oops" 2> /temp/err.msg

또는

 exe_that_writes_to_stderr.exe bogus_arg 2> /temp/err.msg

PowerShell은 오류를 오류 레코드로 기록합니다.오류 레코드의 자세한 출력을 방지하려면 다음과 같이 오류 정보를 직접 작성할 수 있습니다.

PS> Write-Error "oops" -ev ev 2>$null
PS> $ev[0].exception
oops

-EV의줄가입니칭다말임▁(다의 줄임말(입니다.-ErrorVariable모든 오류는 이 매개 변수에 대한 인수로 명명된 변수에 저장됩니다.를 "PowerShell" "PowerShell" "PowerShell"으로 한 합니다.$null.

참고:

  • 이 답변은 PowerShell 스크립트가 외부에서 호출될 때 외부의 관점에서 stderr에게 글을 쓰는 것에 관한 것입니다. 반면 Windows 셸의 관점에서 글을 쓰는 동안,cmd.exe다음과 같은 유닉스 에도 동일하게 적용됩니다.bashPowerShell Core 버전

  • 반대로 Powershell 에서는 다음을 사용해야 합니다.Write-Error키스 힐의 대답에 설명된 바와 같이.

  • 안타깝게도 PowerShell 내부와 외부 모두에서 작동할 수 있는 통합 접근 방식은 없습니다. 자세한 내용은 이 답변을 참조하십시오.


@Chris Sear의 훌륭한 답변에 추가하기:

하는 동안에$host.ui.WriteErrorLine모든 호스트에서 작동해야 하지만 (기본적으로) 배치 파일과 같이 를 통해 호출될 stderr에 쓰지 않습니다. 이와 대조적으로 항상 작동합니다.

따라서 에서 호출할 때 출력 스트림 측면에서 잘 재생되는 PowerShell 스크립트를 작성하려면 다음 함수를 사용합니다.Write-StdErr어떤 것을 사용합니까?[Console]::Error.WriteLinePS에서 / 정에 PS에서 /cmd.exe호스트(호스트 창),$host.ui.WriteErrorLine그렇지 않은 경우:

<#
.SYNOPSIS
Writes text to stderr when running in a regular console window,
to the host''s error stream otherwise.

.DESCRIPTION
Writing to true stderr allows you to write a well-behaved CLI
as a PS script that can be invoked from a batch file, for instance.

Note that PS by default sends ALL its streams to *stdout* when invoked from
cmd.exe.

This function acts similarly to Write-Host in that it simply calls
.ToString() on its input; to get the default output format, invoke
it via a pipeline and precede with Out-String.

#>
function Write-StdErr {
  param ([PSObject] $InputObject)
  $outFunc = if ($Host.Name -eq 'ConsoleHost') {
    [Console]::Error.WriteLine
  } else {
    $host.ui.WriteErrorLine
  }
  if ($InputObject) {
    [void] $outFunc.Invoke($InputObject.ToString())
  } else {
    [string[]] $lines = @()
    $Input | % { $lines += $_.ToString() }
    [void] $outFunc.Invoke($lines -join "`r`n")
  }
}

선택적 배경 정보:외부 호출자가 PowerShell CLI의 출력 스트림을 보는 방법:

내부적으로 PowerShell은 기존의 출력 스트림(stdout 및 stderr)보다 더 많은 것을 보유하고 있으며, 시간이 지남에 따라 그 수가 증가했습니다(시도).Write-Warning "I'll go unheard." 3> $null예를 들어 자세한 내용은 에서 참조하십시오.

외부와 인터페이스할 때 PowerShell은 기존의 출력 스트림이 아닌 것을 stdout 및 stderr에 매핑해야 합니다.

그러나 PowerShell의 오류 스트림을 stderr에 매핑하는 것이 논리적 선택임에도 불구하고 PowerShell은 기본적으로 에서 호출될 때 모든 스트림(및 출력 포함) stdout으로 보냅니다.이 동작은 (최소한) v2 이후부터 적용되었으며 v5.1 현재에도 적용됩니다(이전 버전과의 호환성을 위해 변경되지 않을 수 있습니다. GitHub 문제 #7989 참조).

에서 호출할 경우 다음 명령을 사용하여 이를 확인할 수 있습니다.

powershell -noprofile -command "'out'; Write-Error 'err'; Write-Warning 'warn'; Write-Verbose -Verbose 'verbose'; $DebugPreference='Continue'; write-debug 'debug'; $InformationPreference='Continue'; Write-Information 'info'; Write-Host 'host'; $host.ui.WriteErrorLine('uierr'); [Console]::Error.WriteLine('cerr')" >NUL

은 모든 스트림에 이전 PowerShell과 메시지가됩니다).Write-Information PowerShell v5)에 포함되어 .cmd.exestdout만 리디렉션NUL(, stdout 출력 억제;>NUL).

다음을 제외하고는 출력이 표시되지 않습니다.cerr((으)부터[Console]::Error.WriteLine() - stderr로 되었습니다. - PowerShell의 stdout은 stdout입니다.

아마도 더욱 이상하게도 PowerShell의 오류 스트림을 캡처할 수 있지만 리디렉션이 있어야 합니다.

변경할 경우>NUL2>NUL위는 PowerShell의 오류 스트림이며$host.ui.WriteErrorLine()출력이 억제됩니다. 물론 다른 리디렉션과 마찬가지로 파일로 보낼 수도 있습니다. (설명한 대로,[Console]::Error.WriteLine()] 후자가 리디렉션되는지 여부에 관계없이 항상 stderr로 출력합니다.)

좀 더 집중적인 예를 제시하려면(다시, 에서 실행)cmd.exe):

powershell -noprofile -command "'out'; Write-Error 'err'" 2>NUL

위의 출력만 해당됩니다.out-Write-Error의 출력이 억제됩니다.

요약:

  • 것도 없이 (아것도없이무▁(이없▁without▁any)cmd.exe) 리디렉션 또는 stdout 리디렉션만 사용(>...또는1>...), PowerShell은 모든 출력 스트림을 stdout으로 보냅니다.

  • stderr 리디렉션 포함(2>...), PowerShell오류 스트림을 선택적으로 stderr로 전송합니다(stdout도 리디렉션되는지 여부에 관계없이).

  • 결과적으로, 다음의 일반적인 관용구는 예상대로 작동하지 않습니다.
    powershell ... >data-output.txt이렇게 하면 예상대로 stdout만 파일로 전송되지 않습니다.data-output.txt터미널로 stderr 출력을 인쇄하는 동안, 대신에, 당신은 사용해야 할 것입니다.
    powershell ... >data-output.txt 2>err-output.tmp; type err-output.tmp >&2; del err-output.tmp

따라서 PowerShell은 리디렉션을 인식하고 의도적으로 동작을 조정합니다. (이는 PowerShell에서 컬러 출력을 생성하는 경우에도 분명합니다.)cmd.exe 출력이 파일로 리디렉션될 때 색상 코드를 제거하는 동안 콘솔을 사용합니다.

당신은 아마 이것을 원할 것입니다.

$host.ui.WriteErrorLine('I work in any PowerShell host')

다음과 같은 내용도 표시될 수 있지만 PowerShell 호스트가 콘솔 창/장치라고 가정하므로 유용하지 않다고 생각합니다.

[Console]::Error.WriteLine('I will not work in the PowerShell ISE GUI')

언급URL : https://stackoverflow.com/questions/4998173/how-do-i-write-to-standard-error-in-powershell

반응형