እሴትን ከpowershell መጠየቂያ-ትእዛዝ ወደ SQL አገልጋይ ወኪል በመመለስ ላይ

በበርካታ የ 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 ወይም ለማንኛውም ተለዋዋጭ ሳትሰጥ አገላለጽ ብቻ (ይህም በውጤት ቻናል ላይ በተዘዋዋሪ የሚያመለክት) መሆኑን አስተውያለሁ። በስክሪኑ ላይ ምንም ነገር አይታይም! ይህ የኃይል ሼል ቧንቧው ሥነ ሕንፃ ውጤት ነው - እያንዳንዱ ተግባር የራሱ የውጤት ቧንቧ መስመር አለው ፣ ለእሱ ድርድር ተፈጠረ ፣ እና ወደ እሱ የሚገባው ነገር ሁሉ የተግባር አፈፃፀም ውጤት እንደሆነ ይቆጠራል ፣ የመመለሻ ኦፕሬተሩ የመመለሻ እሴትን ወደ ተመሳሳይ ይጨምራል። የቧንቧ መስመር እንደ የመጨረሻው አካል እና ቁጥጥርን ወደ ጥሪ ተግባር ያስተላልፋል. ለማብራራት፣ የሚከተለውን ስክሪፕት በአገር ውስጥ እናካሂድ፡-

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

ዋናው ተግባር (ስክሪፕት አካል) የራሱ የውጤት ቧንቧ መስመር አለው፣ እና የመጀመሪያውን ስክሪፕት ከሲኤምዲ ብንሰራ ውጤቱን ወደ ፋይል በማዞር፣

PowerShell .TestOutput1.ps1 1 > TestOutput1.txt

ከዚያም በስክሪኑ ላይ እናያለን

ERRORLEVEL=1

እና በፋይሉ ውስጥ

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

ከኃይል ሼል ተመሳሳይ ጥሪ ካደረግን

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

ከዚያም በማያ ገጹ ላይ ይሆናል

Out to host.
ExitCode: 1

እና በፋይሉ ውስጥ

Out to output.
1

ይህ የሆነበት ምክንያት CMD ሌላ መመሪያ በሌለበት ጊዜ ሁለት ክሮች (አስተናጋጅ እና ውፅዓት) በማደባለቅ እና የተቀበለውን ሁሉ ወደ ፋይል ለሚልክ እና ለሲኤምዲ የሚሰጠውን የኃይል ሼል ስለጀመረ እና ከኃይል ሼል በሚነሳበት ጊዜ። እነዚህ ሁለት ክሮች ለየብቻ አሉ፣ እና ምልክቱ አቅጣጫውን የሚያዞረው በውጤት ላይ ብቻ ነው።

ወደ ዋናው ርዕስ ስንመለስ በኃይል ሼል ውስጥ ያለው የ NET የነገር ሞዴል ሙሉ በሙሉ በአንድ ኮምፒዩተር (አንድ ኦኤስ) ውስጥ እንዳለ እናስታውስ በ WSMAN በርቀት ኮድ ሲሰራ የነገሮችን ማስተላለፍ የሚከናወነው በኤክስኤምኤል ተከታታይነት ሲሆን ይህም ብዙ ተጨማሪ ፍላጎትን ያመጣል። ወደ ምርምራችን። የሚከተለውን ኮድ በማስኬድ ሙከራችንን እንቀጥል፡-

$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

ታላቅ ውጤት! ይህ ማለት ኢንቮክ-ትእዛዝን በሚጠራበት ጊዜ የቧንቧ መስመሮች በሁለት ክሮች (አስተናጋጅ እና ውፅዓት) መከፋፈል ተጠብቆ ይቆያል, ይህም ለስኬት ተስፋ ይሰጠናል. በውጤት ዥረቱ ውስጥ አንድ እሴት ብቻ ለመተው እንሞክር፣ ለዚህም በርቀት የምንሰራውን የመጀመሪያውን ስክሪፕት እንለውጣለን።

$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 ዓይነት ተቀይሮ ወደ ተቀባዩ ጎን ተላልፏል እና ተቀባዩ ወገን ተጠቅሞበታል። እንደ ጠሪው የኃይል ሼል መውጫ ኮድ.

እና እንደ የመጨረሻ ፍተሻ፣ በ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.  Шаг завершился с ошибкой.

መደምደሚያ-

  • ጻፍ-ውፅዓትን ከመጠቀም እና መግለጫዎችን ያለ ምደባ ከመግለጽ ይቆጠቡ። ይህንን ኮድ በስክሪፕቱ ውስጥ ወደ ሌላ ቦታ ማዛወር ያልተጠበቀ ውጤት ሊያስገኝ እንደሚችል ልብ ይበሉ።
  • በእጅ ለማስጀመር የታቀዱ ስክሪፕቶች ላይ ሳይሆን በእራስዎ አውቶማቲክ ስልቶች በተለይም በWINRM በኩል ለርቀት ጥሪዎች በእጅ የስህተት አያያዝን በ Try/Catch በኩል ያድርጉ እና በማንኛውም የክስተቶች እድገት ይህ ስክሪፕት በትክክል አንድ ጥንታዊ እሴት እንደሚልክ ያረጋግጡ። . የሚታወቀውን ስህተት ደረጃ ማግኘት ከፈለጉ፣ ይህ ዋጋ ቁጥራዊ መሆን አለበት።

ምንጭ: hab.com

አስተያየት ያክሉ