প্রথম ত্রুটিতে পাওয়ারশেল স্ক্রিপ্ট কীভাবে থামানো যায়?


250

আমি চাই যে আমার চালিত কোনও কমান্ড ব্যর্থ হলে (পাওয়ার মতো set -e) আমার পাওয়ারশেল স্ক্রিপ্টটি বন্ধ হয়ে যায় । আমি পাওয়ারশেল কমান্ড ( New-Object System.Net.WebClient) এবং প্রোগ্রাম ( .\setup.exe) উভয়ই ব্যবহার করছি ।

উত্তর:


303

$ErrorActionPreference = "Stop" আপনাকে সেখানে যাওয়ার অংশটি পেয়ে যাবে (অর্থাত এটি সেমিডলেটগুলির জন্য দুর্দান্ত কাজ করে)।

তবে এক্সইএসগুলির জন্য আপনার প্রতিটি প্রতিবেদনের অনুরোধের $LastExitCodeপরে নিজেকে যাচাই করতে হবে এবং তা ব্যর্থ হয়েছে কিনা তা নির্ধারণ করতে হবে। দুর্ভাগ্যক্রমে আমি ভাবি না যে পাওয়ারশেল এখানে সহায়তা করতে পারে কারণ উইন্ডোজে, এক্সইএসগুলি "সাফল্য" বা "ব্যর্থতা" প্রস্থান কোডটি কীসের উপর নির্ভর করে তা মারাত্মকভাবে সামঞ্জস্য নয়। বেশিরভাগ ইউনিক্স মান অনুসরণ করে 0 সাফল্যের ইঙ্গিত দেয় কিন্তু সব হয় না। পরীক্ষা করে দেখুন এই ব্লগ পোস্টে CheckLastExitCode ফাংশন । আপনি এটি দরকারী মনে হতে পারে।


3
কি $ErrorActionPreference = "Stop"ভালভাবে ভদ্র প্রোগ্রামের জন্য কাজ (যে ফিরতি সাফল্য 0)?
আন্দ্রেস রিওফ্রিয়ো

14
না, এটি EXE- এর জন্য মোটেও কাজ করে না। এটি কেবল পাওয়ারশেল সেমিডলেটগুলির জন্য কাজ করে যা প্রক্রিয়াধীন থাকে। এটি এক ধরনের ব্যথা তবে আপনার প্রতিটি EXE অনুরোধের পরে $ সর্বশেষ এক্সকোট কোডটি পরীক্ষা করে দেখতে হবে, প্রত্যাশিত প্রস্থান কোডের বিরুদ্ধে পরীক্ষা করে দেখুন এবং যদি সেই পরীক্ষাটি ব্যর্থতার ইঙ্গিত দেয় তবে আপনাকে স্ক্রিপ্টটির সম্পাদন বন্ধ করতে নিক্ষেপ করতে হবে যেমন throw "$exe failed with exit code $LastExitCode"$ এক্সপি কেবলমাত্র পথ EXE।
কিথ হিল

2
গৃহীত হয়েছে কারণ এতে বাহ্যিক প্রোগ্রামগুলির সাথে কীভাবে এটি কাজ করা যায় সে সম্পর্কিত তথ্য অন্তর্ভুক্ত রয়েছে।
আন্দ্রেস রিফ্রিও

4
: আমি এখানে এটি সম্পর্কে একটি বৈশিষ্ট্য অনুরোধ রাখা connect.microsoft.com/PowerShell/feedback/details/751703/...
Helephant

5
নোট করুন যে পেকেকে "এক্সিকিউটিভ" নামে একটি কমান্ডলেট রয়েছে যা আপনি লাস্টএক্সিটকোডের জন্য একটি চেক সহ বহিরাগত প্রোগ্রামগুলিতে কলগুলি মোড়ানোর জন্য এবং একটি ত্রুটি প্রদর্শন করতে (এবং যদি ইচ্ছা হয় তবে) থামাতে পারেন
enorl76

68

$ErrorActionPreference = "Stop"আপনার স্ক্রিপ্টগুলির শুরুতে আপনার বিবৃতিটি ব্যবহার করে এটি সম্পাদন করতে সক্ষম হওয়া উচিত ।

ডিফল্ট সেটিং $ErrorActionPreferenceহল Continueত্রুটি ঘটতে পরে, যার কারণে আপনাকে আপনার স্ক্রিপ্টের দেখতে পান বর্তা।


21
এটি প্রোগ্রামগুলিকে প্রভাবিত করে না, কেবল সেমিডলেটগুলি।
জোয়

18

দুঃখের বিষয়, নিউ-রেজি এবং ক্লিয়ার-ডিস্কের মতো বগি সেমিডলেটগুলির কারণে এই উত্তরগুলির কোনওোটাই যথেষ্ট নয়। আমার বোধগম্যতা বজায় রাখতে আমি বর্তমানে কোনও পাওয়ারশেল স্ক্রিপ্টের শীর্ষে নিম্নোক্ত লাইনে স্থির হয়েছি।

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'
}

নেটিভ কল প্যাটার্নটি ধীরে ধীরে আমার পক্ষে যথেষ্ট সাধারণ হয়ে উঠছে যে সম্ভবত এটি আরও সংক্ষিপ্ত করার জন্য আমার বিকল্পগুলির দিকে নজর দেওয়া উচিত। আমি এখনও পাওয়ারশেল নবাগত, তাই পরামর্শগুলি স্বাগত।


14

পাওয়ারশেল ফাংশনগুলির জন্য এবং এক্সের কলিংয়ের জন্য আপনার কিছুটা ভিন্ন ত্রুটি দরকার এবং আপনার স্ক্রিপ্টের কলারকে অবশ্যই এটি নিশ্চিত হওয়া উচিত যে এটি ব্যর্থ হয়েছে। ExecPsake লাইব্রেরি থেকে শীর্ষে বিল্ডিং , নীচের কাঠামোযুক্ত একটি স্ক্রিপ্ট সমস্ত ত্রুটিগুলি থামবে, এবং বেশিরভাগ স্ক্রিপ্টগুলির জন্য বেস টেমপ্লেট হিসাবে ব্যবহারযোগ্য।

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
}

Invoking উদাহরণ: Exec { sqlite3.exe -bail some.db "$SQL" }, -bailএকটি ত্রুটি যেহেতু এটি একটি Cmdlet প্যারামিটার হিসাবে এটা ব্যাখ্যা চাচ্ছে কারণ? উদ্ধৃতিতে জিনিস মোড়ানো কাজ করে বলে মনে হচ্ছে না। কোন ধারনা?
rcoup

এই কোডটি কেন্দ্রীয় কোথাও রাখার কোনও উপায় আছে যাতে আপনি এক্সিকিউট পদ্ধতিটি ব্যবহার করতে চাইলে আপনি কোনও ধরণের # অন্তর্ভুক্ত করতে পারেন?
নিক

10

@ অ্যালেস্টায়ার্ট্রি থেকে উত্তরে সামান্য পরিবর্তন :

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

এখানে মূল পার্থক্যগুলি হ'ল:

  1. এটি ক্রিয়াপদ-বিশেষ্য ব্যবহার করে (নকল করে Invoke-Command)
  2. বোঝায় যে এটি কল অপারেটরগুলি কভারগুলির নীচে ব্যবহার করে
  3. -ErrorActionসেমিডলেটগুলিতে অন্তর্নির্মিত আচরণ থেকে নকল আচরণ
  4. নতুন বার্তা সহ ব্যতিক্রম ছোঁড়ার পরিবর্তে একই প্রস্থান কোড সহ প্রস্থান করে

1
আপনি কীভাবে পরামিতি / ভেরিয়েবলগুলি পাস করবেন? উদাহরণস্বরূপInvoke-Call { dotnet build $something }
মাইকেল ব্লেক

1
@ মিশেলব্লেকে আপনার অনুসন্ধানটি ঠিক আছে, একটি পরম পাসেষ্টার মাধ্যমে এই পদ্ধতির সোনার ব্যবস্থা হবে। আমি অ্যাডম্যাথিয়াটোম্যাটর.com/ pass- hashtables - invoke - command - argument পরিদর্শন করছি ইনভোক-কল সামঞ্জস্য করার জন্য পাসগুলি মাধ্যমে পাস করুন। যদি আমি সফল হই তবে আমি এটি অন্য উত্তর হিসাবে পোস্ট করব।
ম্যাক্সিম ভি ভি পাভলভ

চলার সময় আপনি কেন স্প্ল্যাটিং অপারেটর ব্যবহার করবেন? আপনি কি পেতে পারে? & @ScriptBlockএবং & $ScriptBlockএকই জিনিস প্রদর্শিত হবে। এই ক্ষেত্রে পার্থক্যটি কী তা গুগল করতে সক্ষম হয়নি
গোলাপিফ্লোয়েডএক্স 33

6

আমি পাওয়ারশেলে নতুন কিন্তু এটি সবচেয়ে কার্যকর বলে মনে হচ্ছে:

doSomething -arg myArg
if (-not $?) {throw "Failed to doSomething"}

2

আমি একই জিনিস খুঁজছেন এখানে এসেছেন। $ ত্রুটিঅ্যাকশনপ্রিফারেন্স = "থামান" ততক্ষনে আমার শেলটি মেরে ফেলবে যখন আমি বরং ত্রুটি বার্তাটি দেখি (বিরতি দিন) এটি শেষ হওয়ার আগেই। আমার ব্যাচের সংবেদনশীলতার পিছনে পড়ে:

IF %ERRORLEVEL% NEQ 0 pause & GOTO EOF

আমি দেখতে পেয়েছি যে এটি আমার বিশেষ পিএস 1 লিপির জন্য বেশ একই রকম কাজ করে:

Import-PSSession $Session
If ($? -ne "True") {Pause; Exit}

0

পুনর্নির্দেশ 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.