Баргардонидани арзиш аз powershell invoke-command ба агенти SQL Server

Ҳангоми сохтани методологияи шахсии худ оид ба идоракунии нусхабардорӣ дар серверҳои сершумори MS-SQL, ман вақти зиёдро барои омӯзиши механизми интиқоли арзишҳо дар Powershell ҳангоми зангҳои дурдаст сарф кардам, аз ин рӯ ман ба худ ёдрас мекунам, ки агар он муфид бошад ба каси дигар.

Пас, биёед бо як скрипти оддӣ оғоз кунем ва онро ба таври маҳаллӣ иҷро кунем:

$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

Аҷоиб, сатҳи Errorlevel дар ҷое нопадид шуд, аммо мо бояд арзишро аз скрипт гирем! Биёед сохтмони зеринро санҷем:

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

Ин боз ҳам ҷолибтар аст. Паём дар Натиҷа дар ҷое нопадид шудааст:

Out to host.
ExitCode: 2
ERRORLEVEL=0

Ҳоло, ҳамчун як дурнамои лирикӣ, ман қайд мекунам, ки агар дар дохили як функсияи Powershell шумо Write-Output ё танҳо як ифодаро бидуни таъин кардани он ба ягон тағирёбанда нависед (ва ин ба таври ғайримустақим баромадро ба канали Натиҷаро дар назар дорад), пас ҳатто ҳангоми иҷро кардани маҳаллӣ, дар экран ҳеҷ чиз нишон дода намешавад! Ин натиҷаи меъмории қубури powershell аст - ҳар як функсия қубури баромади худро дорад, барои он массив сохта мешавад ва ҳама чизе, ки ба он дохил мешавад, натиҷаи иҷрои функсия ҳисобида мешавад, оператори Бозгашт арзиши бозгаштро ба ҳамон лӯла ҳамчун унсури охирин ва назоратро ба функсияи даъваткунанда интиқол медиҳад. Барои мисол, биёед скрипти зеринро ба таври маҳаллӣ иҷро кунем:

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

агар мо аз powershell чунин занг занем

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

он гоҳ он дар экран хоҳад буд

Out to host.
ExitCode: 1

ва дар файл

Out to output.
1

Ин аз он сабаб рӯй медиҳад, ки CMD powershell-ро оғоз мекунад, ки дар сурати мавҷуд набудани дастурҳои дигар, ду риштаро (Хост ва Натиҷа) омехта мекунад ва онҳоро ба CMD медиҳад, ки ҳама чизҳои гирифтаашро ба файл мефиристад ва дар сурати аз powershell оғоз кардан, ин ду ришта алоҳида вуҷуд доранд ва масир масир танҳо ба Натиҷа таъсир мерасонад.

Бозгашт ба мавзӯи асосӣ, биёед ба ёд орем, ки модели объекти .NET дар дохили powershell пурра дар дохили як компютер мавҷуд аст (як 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

Биёед кӯшиш кунем, ки чӣ рӯй дод. Мо powershell-ро ба таври маҳаллӣ даъват кардем, ки он дар навбати худ дар компютери дурдаст powershell даъват кард ва скрипти моро дар он ҷо иҷро кард. Ду ҷараён (Хост ва баромад) аз мошини дурдаст силсиласозӣ ва баргардонида шуданд, дар ҳоле ки ҷараёни Натиҷа, ки дар он арзиши ягонаи рақамӣ дорад, ба намуди Int32 табдил дода шуд ва ҳамин тавр ба тарафи қабулкунанда гузашт ва ҷониби қабулкунанда онро истифода бурд. ҳамчун рамзи баромади Powershell зангзананда.

Ва ҳамчун санҷиши ниҳоӣ, биёед кори якқадамро дар сервери SQL бо навъи "Системаи амалиётӣ (cmdexec)" бо матни зерин эҷод кунем:

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.  Шаг завершился с ошибкой.

Натиҷаҳо:

  • Аз истифодаи Write-Output ва муайян кардани ифодаҳо бе таъинот худдорӣ намоед. Огоҳ бошед, ки интиқоли ин код ба ҷои дигаре дар скрипт метавонад ба натиҷаҳои ғайричашмдошт оварда расонад.
  • Дар скриптҳое, ки на барои оғози дастӣ, балки барои истифода дар механизмҳои автоматикунонии шумо, махсусан барои зангҳои дурдаст тавассути WINRM пешбинӣ шудаанд, коркарди хатогиҳоро тавассути Try/Catch анҷом диҳед ва боварӣ ҳосил кунед, ки дар ҳама гуна рушди рӯйдодҳо ин скрипт маҳз як арзиши навъи ибтидоиро мефиристад. . Агар шумо хоҳед, ки дараҷаи хатогии классикиро гиред, ин арзиш бояд ададӣ бошад.

Манбаъ: will.com

Илова Эзоҳ