मैं चाहता हूं कि मेरी पावरशेल स्क्रिप्ट तब बंद हो जाए जब कोई भी कमांड मैं फेल हो जाए (जैसे set -e
बैश में)। मैं Powershell कमांड ( New-Object System.Net.WebClient
) और प्रोग्राम्स ( .\setup.exe
) दोनों का उपयोग कर रहा हूं ।
मैं चाहता हूं कि मेरी पावरशेल स्क्रिप्ट तब बंद हो जाए जब कोई भी कमांड मैं फेल हो जाए (जैसे set -e
बैश में)। मैं Powershell कमांड ( New-Object System.Net.WebClient
) और प्रोग्राम्स ( .\setup.exe
) दोनों का उपयोग कर रहा हूं ।
जवाबों:
$ErrorActionPreference = "Stop"
आपको वहां का हिस्सा मिलेगा (यानी यह cmdlets के लिए बहुत अच्छा काम करता है)।
हालाँकि, $LastExitCode
EXE के लिए आपको हर exe आह्वान के बाद खुद को जाँचना होगा और यह निर्धारित करना होगा कि यह विफल है या नहीं। दुर्भाग्य से मुझे नहीं लगता कि PowerShell यहाँ मदद कर सकता है क्योंकि Windows पर, EXE बहुत "" सफलता "या" विफलता "" निकास कोड का गठन करने पर सुसंगत नहीं हैं। अधिकांश 0 के UNIX मानक का अनुसरण करते हुए सफलता का संकेत देते हैं लेकिन सभी ऐसा नहीं करते हैं। की जाँच करें इस ब्लॉग पोस्ट में CheckLastExitCode समारोह । आपको यह उपयोगी लग सकता है।
throw "$exe failed with exit code $LastExitCode"
जहां $ exe सिर्फ पथ है EXE।
आपको $ErrorActionPreference = "Stop"
अपनी स्क्रिप्ट की शुरुआत में बयान का उपयोग करके इसे पूरा करने में सक्षम होना चाहिए ।
की डिफ़ॉल्ट सेटिंग $ErrorActionPreference
है Continue
, यही कारण है कि आप अपनी स्क्रिप्ट देख रहे हैं त्रुटियों के होने के बाद भी चलते रहें।
अफसोस की बात है कि न्यू-रेग्के और क्लीयर-डिस्क जैसे छोटी गाड़ी सीडलेट्स के कारण , इनमें से कोई भी उत्तर पर्याप्त नहीं है। मैंने वर्तमान में अपनी पवित्रता बनाए रखने के लिए किसी भी शिल्पी लिपि के शीर्ष पर निम्नलिखित पंक्तियों को बसाया है।
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'
}
यह देशी कॉल पैटर्न धीरे-धीरे मेरे लिए काफी सामान्य होता जा रहा है कि मुझे इसे अधिक संक्षिप्त बनाने के विकल्पों पर ध्यान देना चाहिए। मैं अभी भी एक नौसिखिया नौसिखिया हूँ, इसलिए सुझावों का स्वागत है।
आपको पॉवरशेल फ़ंक्शंस के लिए और 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
एक त्रुटि का कारण बनता है? उद्धरणों में चीजों को लपेटना काम नहीं लगता है। कोई विचार?
@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
cmdlets में निर्मित से मिमिक व्यवहारInvoke-Call { dotnet build $something }
& @ScriptBlock
और & $ScriptBlock
एक ही काम करते दिखाई देते हैं। इस मामले में क्या अंतर है यह Google को पता नहीं
मेरा उसी चीज़ को ढूंढते हुए यहाँ तक आना हुआ। $ ErrorActionPreference = "रोकें" मेरे शेल को तुरंत मार देता है जब मैं समाप्त होने से पहले त्रुटि संदेश (पॉज़) देखता हूं। मेरे बैच की संवेदनाओं पर पानी फेरना:
IF %ERRORLEVEL% NEQ 0 pause & GOTO EOF
मैंने पाया कि यह मेरी विशेष ps1 स्क्रिप्ट के लिए बहुत समान है:
Import-PSSession $Session
If ($? -ne "True") {Pause; Exit}
किसी अन्य कमांड / स्क्रिप्टब्लॉक रैपर के बिना भी ट्रिक करने के 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 वापसी)?