Ngabalikeun nilai tina powershell invoke-command ka agén SQL Server

Nalika nyieun metodologi kuring sorangan pikeun ngatur cadangan dina sababaraha server MS-SQL, kuring nyéépkeun seueur waktos diajar mékanisme pikeun ngirimkeun nilai dina Powershell nalika nelepon jarak jauh, janten kuring nyerat panginget ka diri kuring upami éta mangpaat. ka batur.

Janten, hayu urang mimitian ku skrip saderhana sareng jalankeun sacara lokal:

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

Pikeun ngajalankeun skrip, kuring bakal nganggo file CMD di handap ieu, kuring moal kalebet unggal waktos:

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

Dina layar urang bakal ningali ieu:

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


Ayeuna hayu urang ngajalankeun skrip anu sami via WSMAN (jajauheun):

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

Sareng ieu hasilna:

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

Hebat, Errorlevel parantos ngiles dimana waé, tapi urang kedah nampi nilai tina naskah! Hayu urang coba desain handap:

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

Ieu malah leuwih metot. Pesen dina Kaluaran parantos ngaleungit dimana waé:

Out to host.
ExitCode: 2
ERRORLEVEL=0

Ayeuna, salaku digression liris, kuring bakal perhatikeun yén upami di jero fungsi Powershell anjeun nyerat Tulis-Kaluaran atanapi ngan ukur éksprési tanpa masihan kana variabel naon waé (sareng ieu sacara implisit nunjukkeun kaluaran kana saluran Kaluaran), teras sanajan ngajalankeun sacara lokal, euweuh bakal dipintonkeun dina layar! Ieu mangrupikeun konsekuensi tina arsitéktur pipa powershell - unggal fungsi gaduh pipa Output sorangan, hiji Asép Sunandar Sunarya didamel pikeun éta, sareng sadaya anu lebet kana éta dianggap hasil tina palaksanaan fungsi, operator Return nambihan nilai uih deui ka sami. pipeline salaku unsur panungtungan sarta mindahkeun kontrol ka fungsi nelepon. Pikeun ngagambarkeun, hayu urang ngajalankeun skrip ieu sacara lokal:

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

Sareng ieu hasilna:

Main: ParameterValue

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

Fungsi utama (awak naskah) ogé gaduh pipa Kaluaran sorangan, sareng upami urang ngajalankeun skrip munggaran tina CMD, alihan kaluaran kana file,

PowerShell .TestOutput1.ps1 1 > TestOutput1.txt

lajeng urang bakal ningali dina layar

ERRORLEVEL=1

sareng dina file

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

lamun urang nelepon sarupa ti Powershell

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

teras bakal aya dina layar

Out to host.
ExitCode: 1

sareng dina file

Out to output.
1

Ieu kajantenan kusabab CMD ngaluncurkeun powershell, anu, dina henteuna petunjuk anu sanés, nyampur dua utas (Host sareng Output) sareng masihan ka CMD, anu ngirimkeun sadayana anu ditampi kana file, sareng upami diluncurkeun tina Powershell, dua threads ieu aya misah, jeung simbol alihan ngan mangaruhan Kaluaran.

Balik deui ka topik utama, hayu urang émut yén modél obyék .NET di jero Powershell sapinuhna aya dina hiji komputer (hiji OS), nalika ngajalankeun kode jarak jauh via WSMAN, transfer objék lumangsung ngaliwatan serialisasi XML, anu nyababkeun seueur minat tambahan. kana panalungtikan urang. Hayu urang neruskeun percobaan urang ku ngajalankeun kode handap:

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

Sareng ieu anu aya dina layar:

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

Hasil hébat! Ieu ngandung harti yén nalika nelepon Invoke-Command, division tina pipelines kana dua threads (Host jeung Output) dijaga, nu masihan urang harepan sukses. Hayu urang cobian ngan ukur tinggalkeun hiji nilai dina aliran Kaluaran, dimana urang bakal ngarobih naskah anu munggaran anu urang jalankeun jarak jauh:

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

Hayu urang ngajalankeun éta saperti kieu:

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

jeung ... Enya, Sigana mah meunangna!

Out to host.
ExitCode: 4

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


ERRORLEVEL=4

Hayu urang coba ngartos naon anu lumangsung. Urang nyauran powershell sacara lokal, anu dina gilirannana disebut powershell dina komputer jauh sareng ngalaksanakeun naskah urang di dinya. Dua aliran (Host jeung Kaluaran) ti mesin jauh anu serialized sarta diliwatan deui, bari stream Kaluaran, ngabogaan nilai digital tunggal di jerona, dirobah jadi tipe Int32 sarta jadi dibikeun ka sisi panarima, sarta sisi panarima ngagunakeun eta. salaku kode kaluar tina powershell panelepon.

Sareng salaku pamariksaan ahir, hayu urang ngadamel padamelan saléngkah dina pangladén SQL kalayan jinis "Sistem operasi (cmdexec)" kalayan téks ieu:

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

HORAY! Tugas réngsé ku kasalahan, téks dina log:

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

conclusions:

  • Hindarkeun ngagunakeun Tulis-Kaluaran sareng nangtukeun éksprési tanpa ngerjakeun. Sadar yén mindahkeun kode ieu di tempat sanés dina naskah tiasa ngahasilkeun hasil anu teu disangka-sangka.
  • Dina naskah dimaksudkeun lain pikeun peluncuran manual, tapi pikeun pamakéan dina mékanisme automation Anjeun, hususna keur nelepon jauh via WINRM, ngalakukeun penanganan kasalahan manual via Coba / Catch, sarta mastikeun yén, dina sagala ngembangkeun acara, Aksara ieu ngirimkeun persis hiji nilai tipe primitif. . Upami anjeun hoyong kéngingkeun Errorlevel klasik, nilai ieu kedah angka.

sumber: www.habr.com

Tambahkeun komentar