Vegerandina nirxek ji fermana-vekêşana powershell li nûnerê SQL Server

Dema ku metodolojiya xwe ya ji bo birêvebirina hilanînê li ser gelek pêşkêşkerên MS-SQL diafirand, min gelek dem derbas kir ku mekanîzmaya derbaskirina nirxan di Powershell-ê de di dema bangên dûr de lêkolîn kir, ji ber vê yekê ez ji xwe re bîranînek dinivîsim ku ew bikêr be. ji kesekî din re.

Ji ber vê yekê, bila em bi skrîptek hêsan dest pê bikin û wê li herêmî bimeşînin:

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

Ji bo ku nivîsan bimeşîne, ez ê pelê CMD-ya jêrîn bikar bînim, ez ê her carê tê de nekim:

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

Li ser ekranê em ê jêrîn bibînin:

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


Naha em heman skrîptê bi navgîniya WSMAN (ji dûr ve) bimeşînin:

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

Û li vir encam e:

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

Mezin, Errorlevel li cîhek winda bûye, lê pêdivî ye ku em nirxê ji senaryoyê bistînin! Ka em sêwirana jêrîn biceribînin:

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

Ev hê bêtir balkêş e. Peyama di Output de li cîhek winda bû:

Out to host.
ExitCode: 2
ERRORLEVEL=0

Naha, wekî veqetandinek lîrîk, ez ê bibînim ku heke hûn di hundurê fonksiyonek Powershell de hûn Write-Output an jî tenê îfadeyek binivîsin bêyî ku wê ji guhêrbarek re veqetînin (û ev bi nepenî tê wateya derketinê ji kanala Derketinê re), wê hingê tewra dema ku li herêmî tê xebitandin jî, tiştek dê li ser ekranê neyê xuyang kirin! Ev encamek mîmariya lûleya powershell-ê ye - her fonksiyonek lûleya xweya Derketinê heye, ji bo wê rêzek tê afirandin, û her tiştê ku tê de tê wekî encama pêkanîna fonksiyonê tê hesibandin, operatorê Vegerê nirxa vegerê li heman zêde dike. boriyê wekî hêmana dawîn e û kontrolê vediguhezîne fonksiyona bangkirinê. Ji bo ronîkirinê, werin em skrîpta jêrîn bi herêmî bimeşînin:

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: "+$_) }

Û li vir encam e:

Main: ParameterValue

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

Fonksiyona sereke (laşê nivîsarê) di heman demê de lûleya xwe ya Derketinê jî heye, û ger em skrîpta yekem ji CMD-ê bimeşînin, encam ber bi pelek ve vegerînin,

PowerShell .TestOutput1.ps1 1 > TestOutput1.txt

paşê em ê li ser ekranê bibînin

ERRORLEVEL=1

û di dosyayê de

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

ger em bangek weha ji powershell bikin

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

hingê ew ê li ser ekranê be

Out to host.
ExitCode: 1

û di dosyayê de

Out to output.
1

Ev diqewime ji ber ku CMD powershell dest pê dike, ku di nebûna rêwerzên din de, du têlan (Host û Derketin) tevlihev dike û wan dide CMD, ya ku her tiştê ku wergirtiye dişîne pelek, û di bûyera destpêkirina ji powershell de, ev her du mijar ji hev cuda hene, û beralîkirina sembolan tenê bandorê li Derketinê dike.

Em vegerin ser mijara sereke, em ji bîr mekin ku modela tiştên .NET di hundurê powershell de bi tevahî di nav yek komputerê de (yek OS-ê) heye, dema ku kodê ji dûr ve bi riya WSMAN-ê ve tê xebitandin, veguheztina tiştan bi serialîzasyona XML-ê pêk tê, ku ev yek eleqeyek zêde tîne. ji bo lêkolîna me. Ka em ceribandinên xwe bi xebitandina koda jêrîn bidomînin:

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

Û ya ku me li ser ekranê heye ev e:

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

Encama mezin! Wateya wê yekê ye ku dema gazîkirina Invoke-Command tê kirin, dabeşkirina boriyan li du mijaran (Host û Output) tê domandin, ku ji me re hêviya serkeftinê dide. Ka em hewl bidin ku tenê yek nirxek di herika Derketinê de bihêlin, ji bo ku em ê skrîpta yekem a ku em ji dûr ve dimeşînin biguhezînin:

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

Ka em bi vî rengî bimeşînin:

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

û... ERÊ, dişibe serketinê!

Out to host.
ExitCode: 4

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


ERRORLEVEL=4

Werin em hewl bidin ku fêm bikin ka çi qewimî. Me gazî powershell-ê li herêmî kir, ku di encamê de li ser komputera dûr gazî powershell kir û skrîpta me li wir bicîh kir. Du herik (Mêvandar û Derketî) ji makîneya dûr hatin serialîzekirin û paşve hatin derbas kirin, di heman demê de çema Derketinê ku yek nirxek dîjîtal tê de heye, veguherî tîpa Int32 û bi vî rengî derbasî aliyê wergirtinê bû, û aliyê wergir ew bikar anî. wekî koda derketinê ya hêza bangker.

Û wekî kontrolek paşîn, bila em li ser servera SQL bi tîpa "Pergala xebitandinê (cmdexec)" bi nivîsa jêrîn karek yek-gavekî biafirînin:

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

HOORAY! Kar bi xeletiyek qediya, nivîsa di têketinê de:

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

Encamên

  • Ji karanîna Write-Output û diyarkirina îfadeyan bê peywir dûr bixin. Hişyar bin ku veguheztina vê kodê li cîhek din di skrîptê de dibe ku encamên nediyar derxe holê.
  • Di skrîptên ku ne ji bo destpêkirina destan, lê ji bo karanîna di mekanîzmayên xweya otomasyona we de, nemaze ji bo bangên ji dûr ve bi riya WINRM-ê têne armanc kirin, bi riya Try/Catch ve rêgirtina xeletiya destan bikin, û piştrast bikin ku, di her pêşkeftina bûyeran de, ev skrîpt tam nirxek celebek primitive dişîne. . Ger hûn dixwazin asta Errora klasîk bistînin, divê ev nirx hejmar be.

Source: www.habr.com

Add a comment