set -e
bash에서 와 같이 실행하는 명령이 실패하면 PowerShell 스크립트를 중지하고 싶습니다 . Powershell 명령 ( New-Object System.Net.WebClient
)과 프로그램 ( .\setup.exe
) 을 모두 사용 하고 있습니다 .
set -e
bash에서 와 같이 실행하는 명령이 실패하면 PowerShell 스크립트를 중지하고 싶습니다 . Powershell 명령 ( New-Object System.Net.WebClient
)과 프로그램 ( .\setup.exe
) 을 모두 사용 하고 있습니다 .
답변:
$ErrorActionPreference = "Stop"
이 방법의 일부를 제공합니다 (즉, 이는 cmdlet에 효과적입니다).
그러나 EXE의 경우 $LastExitCode
모든 exe 호출 후 자신 을 확인 하고 실패 여부를 결정해야합니다. 불행히도 Windows에서는 EXE가 "성공"또는 "실패"종료 코드를 구성하는 요소와 크게 일치하지 않기 때문에 PowerShell이 여기에서 도움을 줄 수 없다고 생각합니다. 대부분의 성공을 나타내는 UNIX 표준 0을 따르지만 모두 그렇지는 않습니다. 이 블로그 게시물에서 CheckLastExitCode 함수를 확인하십시오 . 유용 할 수 있습니다.
throw "$exe failed with exit code $LastExitCode"
$ exe가 경로입니다) EXE.
안타깝게도 New-RegKey 및 Clear-Disk와 같은 버그가있는 cmdlet으로 인해 이러한 답변으로는 충분하지 않습니다. 나는 현재 나의 건강을 유지하기 위해 powershell 스크립트의 맨 위에 다음 줄을 정했다.
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
그런 다음 모든 기본 전화 가이 처리를 얻습니다.
native_call.exe
$native_call_success = $?
if (-not $native_call_success)
{
throw 'error making native call'
}
그 기본 통화 패턴은 천천히 간결 해지기 때문에 옵션을 더 간결하게 만들기 위해 선택해야합니다. 저는 여전히 파워 쉘 초보자이므로 제안을 환영합니다.
powershell 함수와 exe 호출에 대해 약간 다른 오류 처리가 필요하며 스크립트 호출자에게 실패했음을 알려야합니다. Exec
라이브러리 Psake에서 빌드 하면 아래 구조를 가진 스크립트는 모든 오류에서 중지되며 대부분의 스크립트에 대한 기본 템플릿으로 사용할 수 있습니다.
Set-StrictMode -Version latest
$ErrorActionPreference = "Stop"
# Taken from psake https://github.com/psake/psake
<#
.SYNOPSIS
This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode
to see if an error occcured. If an error is detected then an exception is thrown.
This function allows you to run command-line programs without having to
explicitly check the $lastexitcode variable.
.EXAMPLE
exec { svn info $repository_trunk } "Error executing SVN. Please verify SVN command-line client is installed"
#>
function Exec
{
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,
[Parameter(Position=1,Mandatory=0)][string]$errorMessage = ("Error executing command {0}" -f $cmd)
)
& $cmd
if ($lastexitcode -ne 0) {
throw ("Exec: " + $errorMessage)
}
}
Try {
# Put all your stuff inside here!
# powershell functions called as normal and try..catch reports errors
New-Object System.Net.WebClient
# call exe's and check their exit code using Exec
Exec { setup.exe }
} Catch {
# tell the caller it has all gone wrong
$host.SetShouldExit(-1)
throw
}
Exec { sqlite3.exe -bail some.db "$SQL" }
의는 -bail
cmdlet은 매개 변수로 해석하려고하기 때문에 오류가 발생합니다? 따옴표로 묶는 것은 효과가없는 것 같습니다. 어떤 아이디어?
@alastairtree 의 답변 을 약간 수정했습니다 .
function Invoke-Call {
param (
[scriptblock]$ScriptBlock,
[string]$ErrorAction = $ErrorActionPreference
)
& @ScriptBlock
if (($lastexitcode -ne 0) -and $ErrorAction -eq "Stop") {
exit $lastexitcode
}
}
Invoke-Call -ScriptBlock { dotnet build . } -ErrorAction Stop
주요 차이점은 다음과 같습니다.
Invoke-Command
)를 사용합니다.-ErrorAction
기본 제공 cmdlet의 동작 모방Invoke-Call { dotnet build $something }
& @ScriptBlock
과 & $ScriptBlock
같은 일을 할 것으로 보인다. 차이가이 경우에 무엇 구글 수 없었다
재 지정 stderr
하려면 stdout
그런 식으로 작동 왜 설명을 찾을 수 있지만 또한 다른 명령 / 스크립트 블록 래퍼없이 트릭을 할 것 같다 ..
# test.ps1
$ErrorActionPreference = "Stop"
aws s3 ls s3://xxx
echo "==> pass"
aws s3 ls s3://xxx 2>&1
echo "shouldn't be here"
예상대로 다음을 출력합니다 (명령 aws s3 ...
은을 반환합니다 $LASTEXITCODE = 255
)
PS> .\test.ps1
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
==> pass
$ErrorActionPreference = "Stop"
잘 동작하는 프로그램에 대한 작업을 (를 돌려 성공 0)?