د SQL سرور اجنټ ته د پاورشیل انووک کمانډ څخه د ارزښت بیرته راګرځول

کله چې په ډیری MS-SQL سرورونو کې د بیک اپ اداره کولو لپاره زما خپل میتودولوژي رامینځته کړه ، ما د لرې تلیفونونو په جریان کې په پاورشیل کې د ارزښتونو تیرولو میکانیزم مطالعه کولو ډیر وخت تیر کړ ، نو زه خپل ځان ته یو یادونه لیکم که چیرې دا ګټور وي بل چا ته.

نو، راځئ چې د یو ساده سکریپټ سره پیل وکړو او په محلي توګه یې پرمخ بوځو:

$exitcode = $args[0]
Write-Host 'Out to host.'
Write-Output 'Out to output.'
Write-Host ('ExitCode: ' + $exitcode)
Write-Output $exitcode
$host.SetShouldExit($exitcode)

د سکریپټونو چلولو لپاره، زه به لاندې د CMD فایل وکاروم، زه به دا هر ځل شامل نه کړم:

@Echo OFF
PowerShell .TestOutput1.ps1 1
ECHO ERRORLEVEL=%ERRORLEVEL%

په سکرین کې به موږ لاندې وګورو:

Out to host.
Out to output.
ExitCode: 1
1
ERRORLEVEL=1


اوس راځئ چې ورته سکریپټ د WSMAN له لارې پرمخ بوځو (د لیرې څخه):

Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]

او دلته پایله ده:

Out to host.
Out to output.
ExitCode: 2
2
ERRORLEVEL=0

عالي ، د خطا کچه یو څه ورکه شوې ، مګر موږ اړتیا لرو له سکریپټ څخه ارزښت ترلاسه کړو! راځئ چې لاندې ډیزاین هڅه وکړو:

$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]

دا نور هم په زړه پورې دی. په آوټ پټ کې پیغام چیرته ورک شوی دی:

Out to host.
ExitCode: 2
ERRORLEVEL=0

اوس، د یو شعري تحلیل په توګه، زه به یادونه وکړم چې که د پاورشیل فنکشن دننه تاسو Write-Output یا یوازې یو بیان ولیکئ پرته لدې چې دا کوم متغیر ته وټاکئ (او دا په واضح ډول د آوټ پوټ چینل ته محصول معنی لري)، بیا حتی کله چې په محلي توګه چلیږي، هیڅ شی به په سکرین کې ونه ښودل شي! دا د پاورشیل پایپ لاین جوړښت پایله ده - هر فنکشن خپل د محصول پایپ لاین لري ، د دې لپاره یو سرې رامینځته کیږي ، او هرڅه چې پدې کې تیریږي د فنکشن اجرا کولو پایله ګڼل کیږي ، د بیرته راستنیدو آپریټر ورته د بیرته ستنیدو ارزښت اضافه کوي. پایپ لاین د وروستي عنصر په توګه او د تلیفون فعالیت ته کنټرول لیږدوي. د روښانه کولو لپاره، راځئ چې لاندې سکریپټ په ځایی توګه پرمخ بوځو:

Function Write-Log {
  Param( [Parameter(Mandatory=$false, ValueFromPipeline=$true)] [String[]] $OutString = "`r`n" )
  Write-Output ("Function: "+$OutString)
  Return "ReturnValue"
}
Write-Output ("Main: "+"ParameterValue")
$res = Write-Log "ParameterValue"
$res.GetType()
$res.Length
$res | Foreach-Object { Write-Host ("Main: "+$_) }

او دلته پایله ده:

Main: ParameterValue

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
2
Main: Function: ParameterValue
Main: ReturnValue

اصلي فنکشن (د سکریپټ باډي) هم خپل د آوټ پټ پایپ لاین لري، او که موږ د CMD څخه لومړی سکریپټ چلوو، د محصول فایل ته لیږدول،

PowerShell .TestOutput1.ps1 1 > TestOutput1.txt

بیا به موږ په سکرین کې وګورو

ERRORLEVEL=1

او په دوتنه کې

Out to host.
Out to output.
ExitCode: 1
1

که موږ د پاورشیل څخه ورته تلیفون وکړو

PS D:sqlagent> .TestOutput1.ps1 1 > TestOutput1.txt

بیا به په سکرین کې وي

Out to host.
ExitCode: 1

او په دوتنه کې

Out to output.
1

دا پیښیږي ځکه چې CMD پاورشیل په لاره اچوي، کوم چې د نورو لارښوونو په نشتوالي کې، دوه تارونه (میزبان او آوټ پټ) مخلوط کوي او CMD ته یې ورکوي، کوم چې هر څه ترلاسه شوي فایل ته لیږي، او د پاورشیل څخه د چلولو په صورت کې، دا دوه تارونه په جلا توګه شتون لري، او سمبول ریډیریکټ یوازې په محصول اغیزه کوي.

اصلي موضوع ته بیرته راګرځیدو، اجازه راکړئ په یاد ولرئ چې د پاورشیل دننه د .NET اعتراض ماډل په بشپړ ډول په یو کمپیوټر کې شتون لري (یو OS)، کله چې د WSMAN له لارې لرې کوډ چلوي، د شیانو لیږد د XML سیریل کولو له لارې واقع کیږي، کوم چې ډیرې اضافي ګټې راوړي. زموږ څیړنې ته. راځئ چې د لاندې کوډ په چلولو سره خپلو تجربو ته دوام ورکړو:

$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
$res.GetType()
$host.SetShouldExit($res)

او دا هغه څه دي چې موږ یې په سکرین کې لرو:

Out to host.

ExitCode: 3

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
Не удается преобразовать аргумент "exitCode", со значением: "System.Object[]", для "SetShouldExit" в тип "System.Int32": "Не удается преобразовать значение "System.Object[]" типа "System.Object[]" в тип "System
.Int32"."
D:sqlagentTestOutput3.ps1:3 знак:1
+ $host.SetShouldExit($res)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

ERRORLEVEL=0

عالي پایله! دا پدې مانا ده چې کله د Invoke-command زنګ ووهئ، د پایپ لاینونو ویش په دوو تارونو (میزبان او محصول) ساتل کیږي، کوم چې موږ ته د بریالیتوب هیله راکوي. راځئ هڅه وکړو چې یوازې یو ارزښت د آوټ پټ سټریم کې پریږدو ، د کوم لپاره چې موږ به لومړی سکریپټ بدل کړو چې موږ یې له لرې چلوو:

$exitcode = $args[0]
Write-Host 'Out to host.'
#Write-Output 'Out to output.'
Write-Host ('ExitCode: ' + $exitcode)
Write-Output $exitcode
$host.SetShouldExit($exitcode)

راځئ چې دا په دې ډول پرمخ بوځو:

$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
$host.SetShouldExit($res)

او... هو، دا د بریا په څیر ښکاري!

Out to host.
ExitCode: 4

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType


ERRORLEVEL=4

راځئ هڅه وکړو چې معلومه کړو چې څه پیښ شوي. موږ په محلي ډول پاورشیل ته زنګ وواهه، کوم چې په پایله کې یې په ریموټ کمپیوټر کې پاورشیل ویل او زموږ سکریپټ یې هلته اجرا کړ. د ریموټ ماشین څخه دوه جریانونه (میزبان او آوټ پوټ) سیریل شوي او بیرته تیریدل ، پداسې حال کې چې د آوټ پوټ جریان چې یو واحد ډیجیټل ارزښت لري ، په Int32 ډوله بدل شوی او پدې توګه ترلاسه کونکي اړخ ته لیږدول شوی ، او ترلاسه کونکي اړخ یې کارولی. د زنګ وهونکي پاورشیل د وتلو کوډ په توګه.

او د وروستي چک په توګه ، راځئ چې د لاندې متن سره د "عملیاتي سیسټم (cmdexec)" ډول سره په SQL سرور کې یو ګام دنده رامینځته کړو:

PowerShell -NonInteractive -NoProfile "$res=Invoke-Command -ComputerName BACKUPSERVER -ConfigurationName SQLAgent -ScriptBlock {&'D:sqlagentTestOutput1.ps1' 6}; $host.SetShouldExit($res)"

هورې! دنده د خطا سره بشپړه شوه، په لاګ کې متن:

Выполняется от имени пользователя: DOMAINagentuser. Out to host. ExitCode: 6.  Код завершения процесса 6.  Шаг завершился с ошибкой.

پایلې:

  • د لیکلو محصول کارولو څخه ډډه وکړئ او د دندې پرته د توضیحاتو مشخص کول. په یاد ولرئ چې دا کوډ په سکریپټ کې بل چیرې لیږدول ممکن غیر متوقع پایلې رامینځته کړي.
  • په سکریپټونو کې چې د لاسي لانچ لپاره نه وي ، مګر ستاسو د اتومات میکانیزمونو کې د کارولو لپاره ، په ځانګړي توګه د WINRM له لارې د ریموټ تلیفونونو لپاره ، د Try/Catch له لارې لاسي غلطي اداره کړئ ، او ډاډ ترلاسه کړئ چې د پیښو په هر پرمختګ کې ، دا سکریپټ دقیقا یو لومړني ډول ارزښت لیږي. . که تاسو غواړئ د کلاسیک غلطی کچه ترلاسه کړئ، دا ارزښت باید عددي وي.

سرچینه: www.habr.com

Add a comment