์ฌ๋ฌ 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