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 ශ්‍රිතයක් තුළ ඔබ ලියන්නේ-ප්‍රතිදානය හෝ ප්‍රකාශනයක් කිසියම් විචල්‍යයකට පැවරීමකින් තොරව (සහ මෙය ප්‍රතිදානය නාලිකාවට ව්‍යංගයෙන් ඇඟවුම් කරයි), දේශීයව ධාවනය වන විට පවා, තිරය ​​මත කිසිවක් නොපෙන්වයි! මෙය පවර්ෂෙල් නල මාර්ග ගෘහ නිර්මාණ ශිල්පයේ ප්‍රතිවිපාකයකි - සෑම ශ්‍රිතයකටම තමන්ගේම ප්‍රතිදාන නල මාර්ගයක් ඇත, ඒ සඳහා අරාවක් සාදනු ලැබේ, සහ එයට ඇතුළු වන සෑම දෙයක්ම ශ්‍රිත ක්‍රියාත්මක කිරීමේ ප්‍රති result ලයක් ලෙස සලකනු ලැබේ, ආපසු එන ක්‍රියාකරු ප්‍රතිලාභ අගය එයට එක් කරයි. නල මාර්ගය අවසාන අංගය ලෙස සහ ඇමතුම් කාර්යයට පාලනය මාරු කරයි. නිදර්ශනය කිරීම සඳහා, පහත ස්ක්‍රිප්ටය දේශීයව ධාවනය කරමු:

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 දියත් කරන අතර, එය වෙනත් උපදෙස් නොමැති විට, නූල් දෙකක් (Host සහ Output) මිශ්‍ර කර CMD වෙත ලබා දෙන අතර, එය ගොනුවකට ලැබුණු සියල්ල යවන අතර, powershell වෙතින් දියත් කිරීමේදී, මෙම නූල් දෙක වෙන වෙනම පවතින අතර සංකේත යළි-යොමුවීම් ප්‍රතිදානයට පමණක් බලපායි.

ප්‍රධාන මාතෘකාවට ආපසු යාමේදී, පවර්ෂෙල් තුළ ඇති .NET වස්තු ආකෘතිය එක් පරිගණකයක් (එක් මෙහෙයුම් පද්ධතියක්) තුළ සම්පූර්ණයෙන්ම පවතින බව මතක තබා ගනිමු, 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 ඇමතීමේදී, නල මාර්ග නූල් දෙකකට (Host සහ Output) බෙදීම පවත්වා ගෙන යන අතර එමඟින් අපට සාර්ථකත්වය සඳහා බලාපොරොත්තුවක් ලබා දේ. ප්‍රතිදාන ප්‍රවාහයේ එක් අගයක් පමණක් තැබීමට උත්සාහ කරමු, ඒ සඳහා අපි දුරස්ථව ධාවනය කරන පළමු ස්ක්‍රිප්ට් එක වෙනස් කරන්නෙමු:

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

නිගමන:

  • පැවරීමකින් තොරව Write-Output භාවිතයෙන් සහ ප්‍රකාශන සඳහන් කිරීමෙන් වළකින්න. මෙම කේතය ස්ක්‍රිප්ටයේ වෙනත් තැනකට ගෙන යාමෙන් අනපේක්ෂිත ප්‍රතිඵල ඇති විය හැකි බව සලකන්න.
  • අතින් දියත් කිරීම සඳහා නොව, ඔබේ ස්වයංක්‍රීය යාන්ත්‍රණවල භාවිතය සඳහා, විශේෂයෙන්ම WINRM හරහා දුරස්ථ ඇමතුම් සඳහා, උත්සාහ/අල්ලා ගැනීම හරහා අතින් දෝෂ හැසිරවීම සිදු කරන්න, සහ සිදුවීම්වල ඕනෑම වර්ධනයකදී, මෙම ස්ක්‍රිප්ටය හරියටම එක් ප්‍රාථමික ආකාරයේ අගයක් යවන බව සහතික කර ගන්න. . ඔබට සම්භාව්‍ය දෝෂ මට්ටම ලබා ගැනීමට අවශ්‍ය නම්, මෙම අගය සංඛ්‍යාත්මක විය යුතුය.

මූලාශ්රය: www.habr.com

DDoS ආරක්ෂාව, VPS VDS සේවාදායකයන් සහිත අඩවි සඳහා විශ්වාසදායක සත්කාරකත්වය මිලදී ගන්න 🔥 DDoS ආරක්ෂාව, VPS VDS සේවාදායකයන් සහිත විශ්වාසදායක වෙබ් අඩවි සත්කාරකත්වය මිලදී ගන්න | ProHoster