Meta ħoloq il-metodoloġija tiegħi stess għall-ġestjoni tal-backups fuq servers MS-SQL multipli, qattajt ħafna ħin nistudja l-mekkaniżmu biex tgħaddi l-valuri f'Powershell waqt sejħiet mill-bogħod, għalhekk qed nikteb tfakkira lili nnifsi f'każ li jkun utli. lil xi ħadd ieħor.
Allura, ejja nibdew bi skript sempliċi u mexxih lokalment:
$exitcode = $args[0]
Write-Host 'Out to host.'
Write-Output 'Out to output.'
Write-Host ('ExitCode: ' + $exitcode)
Write-Output $exitcode
$host.SetShouldExit($exitcode)
Biex tmexxi skripts, se nuża l-fajl CMD li ġej, mhux se ninkludih kull darba:
@Echo OFF
PowerShell .TestOutput1.ps1 1
ECHO ERRORLEVEL=%ERRORLEVEL%
Fuq l-iskrin se naraw dan li ġej:
Out to host.
Out to output.
ExitCode: 1
1
ERRORLEVEL=1
Issa ejja nħaddmu l-istess skript permezz ta' WSMAN (b'mod remot):
Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
U hawn hu r-riżultat:
Out to host.
Out to output.
ExitCode: 2
2
ERRORLEVEL=0
Kbir, Errorlevel sparixxa x'imkien, imma rridu nġibu l-valur mill-iskrittura! Ejja nippruvaw il-kostruzzjoni li ġejja:
$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
Dan huwa saħansitra aktar interessanti. Il-messaġġ fl-Output sparixxa x'imkien:
Out to host.
ExitCode: 2
ERRORLEVEL=0
Issa, bħala digressjoni lirika, ser ninnota li jekk ġewwa funzjoni Powershell tikteb Write-Output jew sempliċiment espressjoni mingħajr ma tassenjaha għal xi varjabbli (u dan jimplika impliċitament output għall-kanal Output), allura anke meta taħdem lokalment, xejn mhu se jintwera fuq l-iskrin! Din hija konsegwenza tal-arkitettura tal-pipeline powershell - kull funzjoni għandha l-pipeline Output tagħha stess, tinħoloq firxa għaliha, u dak kollu li jidħol fih jitqies bħala r-riżultat tal-eżekuzzjoni tal-funzjoni, l-operatur Ritorn iżid il-valur tar-ritorn għall-istess pipeline bħala l-aħħar element u jittrasferixxi l-kontroll lill-funzjoni li ssejjaħ. Biex nagħtu eżempju, ejja nħaddmu l-iskrittura li ġejja lokalment:
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: "+$_) }
U hawn hu r-riżultat:
Main: ParameterValue
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
2
Main: Function: ParameterValue
Main: ReturnValue
Il-funzjoni ewlenija (korp tal-iskrittura) għandha wkoll il-pipeline tal-Output tagħha stess, u jekk inħaddmu l-ewwel skript minn CMD, nidderieġu l-output għal fajl,
PowerShell .TestOutput1.ps1 1 > TestOutput1.txt
imbagħad naraw fuq l-iskrin
ERRORLEVEL=1
u fil-fajl
Out to host.
Out to output.
ExitCode: 1
1
jekk nagħmlu sejħa simili minn powershell
PS D:sqlagent> .TestOutput1.ps1 1 > TestOutput1.txt
imbagħad ikun fuq l-iskrin
Out to host.
ExitCode: 1
u fil-fajl
Out to output.
1
Dan jiġri minħabba li s-CMD iniedi powershell, li, fin-nuqqas ta 'struzzjonijiet oħra, iħallat żewġ ħjut (Host u Output) u jagħtihom lis-CMD, li jibgħat dak kollu li rċieva f'fajl, u fil-każ li jaħdem minn powershell, dawn iż-żewġ ħjut jeżistu separatament, u r-ridirezzjonijiet tas-simbolu jaffettwaw biss l-Output.
Nirritornaw għas-suġġett ewlieni, ejjew niftakru li l-mudell ta 'oġġett .NET ġewwa powershell jeżisti bis-sħiħ fi ħdan kompjuter wieħed (OS wieħed), meta tħaddem kodiċi mill-bogħod permezz ta' WSMAN, it-trasferiment ta 'oġġetti jseħħ permezz ta' serialization XML, li jġib ħafna interess addizzjonali għar-riċerka tagħna. Ejja nkomplu bl-esperimenti tagħna billi nħaddmu l-kodiċi li ġej:
$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
$res.GetType()
$host.SetShouldExit($res)
U dan huwa dak li għandna fuq l-iskrin:
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
Riżultat kbir! Dan ifisser li meta ssejjaħ Invoke-Command, tinżamm id-diviżjoni tal-pipelines f'żewġ ħjut (Host u Output), li tagħtina tama għas-suċċess. Ejja nippruvaw inħallu valur wieħed biss fil-fluss Output, li għalih se nibdlu l-ewwel skript li nħaddmu mill-bogħod:
$exitcode = $args[0]
Write-Host 'Out to host.'
#Write-Output 'Out to output.'
Write-Host ('ExitCode: ' + $exitcode)
Write-Output $exitcode
$host.SetShouldExit($exitcode)
Ejja nħaddmu hekk:
$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
$host.SetShouldExit($res)
u... IVA, qisu rebħa!
Out to host.
ExitCode: 4
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
ERRORLEVEL=4
Ejja nippruvaw insemmu x'ġara. Aħna sejjaħ powershell lokalment, li mbagħad sejjaħ powershell fuq il-kompjuter remot u eżegwiti l-iskrittura tagħna hemmhekk. Żewġ flussi (Host u Output) mill-magna remota ġew serialized u mgħoddija lura, filwaqt li l-fluss tal-Output, li għandu valur diġitali wieħed fih, ġie kkonvertit għal tip Int32 u bħala tali għadda għan-naħa li tirċievi, u n-naħa li tirċievi użatha bħala l-kodiċi tal-ħruġ tal-powershell min iċempel.
U bħala kontroll finali, ejja noħolqu xogħol f'pass wieħed fuq is-server SQL bit-tip "Sistema operattiva (cmdexec)" bit-test li ġej:
PowerShell -NonInteractive -NoProfile "$res=Invoke-Command -ComputerName BACKUPSERVER -ConfigurationName SQLAgent -ScriptBlock {&'D:sqlagentTestOutput1.ps1' 6}; $host.SetShouldExit($res)"
HURA! Il-kompitu tlesta bi żball, test fil-ġurnal:
Выполняется от имени пользователя: DOMAINagentuser. Out to host. ExitCode: 6. Код завершения процесса 6. Шаг завершился с ошибкой.
Konklużjonijiet:
- Evita li tuża Write-Output u tispeċifika espressjonijiet mingħajr assenjazzjoni. Kun konxju li ċaqliq ta' dan il-kodiċi xi mkien ieħor fl-iskript jista' jipproduċi riżultati mhux mistennija.
- Fi skripts maħsuba mhux għat-tnedija manwali, iżda għall-użu fil-mekkaniżmi ta' awtomazzjoni tiegħek, speċjalment għal sejħiet mill-bogħod permezz ta' WINRM, agħmel immaniġġjar manwali tal-iżbalji permezz Try/Catch, u żgura li, fi kwalunkwe żvilupp ta' avvenimenti, dan l-iskript jibgħat eżattament valur wieħed tat-tip primittiv . Jekk trid tikseb l-Errorlevel klassika, dan il-valur għandu jkun numeriku.
Sors: www.habr.com