powershell ํ˜ธ์ถœ ๋ช…๋ น์—์„œ 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 ํŒŒ์ดํ”„๋ผ์ธ ์•„ํ‚คํ…์ฒ˜์˜ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๊ฐ ํ•จ์ˆ˜์—๋Š” ์ž์ฒด ์ถœ๋ ฅ ํŒŒ์ดํ”„๋ผ์ธ์ด ์žˆ๊ณ  ์ด์— ๋Œ€ํ•œ ๋ฐฐ์—ด์ด ์ƒ์„ฑ๋˜๋ฉฐ ์—ฌ๊ธฐ์— ๋“ค์–ด๊ฐ€๋Š” ๋ชจ๋“  ๊ฒƒ์€ ํ•จ์ˆ˜ ์‹คํ–‰์˜ ๊ฒฐ๊ณผ๋กœ ๊ฐ„์ฃผ๋˜๋ฉฐ Return ์—ฐ์‚ฐ์ž๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์„ ๋™์ผํ•œ ํŒŒ์ดํ”„๋ผ์ธ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งˆ์ง€๋ง‰ ์š”์†Œ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์ œ์–ด๋ฅผ ํ˜ธ์ถœ ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์„ค๋ช…์„ ์œ„ํ•ด ๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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๊ฐ€ ๋‹ค๋ฅธ ๋ช…๋ น์ด ์—†๋Š” ๊ฒฝ์šฐ ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ(ํ˜ธ์ŠคํŠธ ๋ฐ ์ถœ๋ ฅ)๋ฅผ ํ˜ผํ•ฉํ•˜์—ฌ CMD์— ์ œ๊ณตํ•˜๋Š” powershell์„ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. CMD๋Š” ๋ฐ›์€ ๋ชจ๋“  ๊ฒƒ์„ ํŒŒ์ผ๋กœ ๋ณด๋‚ด๊ณ , powershell์—์„œ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ์ด ๋‘ ์Šค๋ ˆ๋“œ๋Š” ๋ณ„๋„๋กœ ์กด์žฌํ•˜๋ฉฐ ๊ธฐํ˜ธ ๋ฆฌ๋””๋ ‰์…˜์€ ์ถœ๋ ฅ์—๋งŒ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค.

์ฃผ์š” ์ฃผ์ œ๋กœ ๋Œ์•„๊ฐ€์„œ, powershell ๋‚ด๋ถ€์˜ .NET ๊ฐœ์ฒด ๋ชจ๋ธ์€ ํ•˜๋‚˜์˜ ์ปดํ“จํ„ฐ(ํ•˜๋‚˜์˜ 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๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํŒŒ์ดํ”„๋ผ์ธ์ด ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ(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

๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ฌ๋Š”์ง€ ์•Œ์•„๋‚ด๋ ค๊ณ  ๋…ธ๋ ฅํ•ฉ์‹œ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋กœ์ปฌ์—์„œ powershell์„ ํ˜ธ์ถœํ–ˆ๊ณ , ์›๊ฒฉ ์ปดํ“จํ„ฐ์—์„œ powershell์„ ํ˜ธ์ถœํ•˜์—ฌ ๊ทธ๊ณณ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์›๊ฒฉ ์‹œ์Šคํ…œ์˜ ๋‘ ์ŠคํŠธ๋ฆผ(ํ˜ธ์ŠคํŠธ ๋ฐ ์ถœ๋ ฅ)์ด ์ง๋ ฌํ™”๋˜์–ด ๋‹ค์‹œ ์ „๋‹ฌ๋˜๋Š” ๋ฐ˜๋ฉด, ๋‹จ์ผ ๋””์ง€ํ„ธ ๊ฐ’์„ ํฌํ•จํ•˜๋Š” ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ์€ Int32 ์œ ํ˜•์œผ๋กœ ๋ณ€ํ™˜๋˜์–ด ์ˆ˜์‹ ์ธก์œผ๋กœ ์ „๋‹ฌ๋˜๊ณ  ์ˆ˜์‹ ์ธก์—์„œ๋Š” ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ˜ธ์ถœ์ž powershell์˜ ์ข…๋ฃŒ ์ฝ”๋“œ๋กœ.

๋งˆ์ง€๋ง‰ ํ™•์ธ์œผ๋กœ ๋‹ค์Œ ํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ "์šด์˜ ์ฒด์ œ(cmdexec)" ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ SQL ์„œ๋ฒ„์—์„œ XNUMX๋‹จ๊ณ„ ์ž‘์—…์„ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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๋ฅผ ํ†ตํ•ด ์ˆ˜๋™ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ด๋ฒคํŠธ ๊ฐœ๋ฐœ ์‹œ ์ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ •ํ™•ํžˆ ํ•˜๋‚˜์˜ ๊ธฐ๋ณธ ์œ ํ˜• ๊ฐ’์„ ์ „์†กํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. . ์ „ํ˜•์ ์ธ Errorlevel์„ ์–ป์œผ๋ ค๋ฉด ์ด ๊ฐ’์€ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€