перехват кода возврата команды с помощью «invoke-command» — Powershell 2
-
06-07-2019 - |
Вопрос
Я использую команду «invoke» для выполнения сценария на удаленном компьютере.
invoke-command -computername <server_name> -scriptblock {command to execute the script}
Мой скрипт возвращает «-1» при возникновении ошибок.Итак, я хотел убедиться, что сценарий выполнен успешно, проверив код возврата.
Я попробовал следующим образом.
$code = invoke-command -computername ....
Но он ничего не возвращает.
Не Invoke-command
поймать код возврата блока скрипта?
Есть ли другой способ решить эту проблему?
Решение
Я думаю, что если вы запустите команду таким образом на другом сервере, вы не сможете найти код возврата вашего сценария. Это потому, что Invoke-Command
просто запускает одну команду на удаленном компьютере, возможно, в течение одного временного сеанса, и вы не можете подключиться к этому сеансу снова.
Что вы можете сделать, так это создать сеанс на удаленном компьютере и запустить ваш сценарий в этом сеансе. После этого вы можете просто проверить возвращаемое значение в этом сеансе снова. Так что-то вроде:
$s = New-PSSession -ComputerName <server_name>
Invoke-Command -Session $s -ScriptBlock { ... }
Invoke-Command -Session $s -ScriptBlock { $? }
может сработать. Таким образом, вы получаете доступ к тому же состоянию и переменным, что и первая Invoke-Command
на удаленном компьютере.
Также Invoke-Command
вряд ли пройдет через возвращаемое значение удаленной команды. Как бы вы выяснили, что Invoke-Command
сама по себе не удалась?
ETA: Хорошо, я неправильно понял вас по поводу "кода возврата". Я предполагал, что вы имели в виду $?
. В любом случае, согласно документации, вы можете запустить скрипт на удаленном компьютере следующим образом:
Чтобы запустить локальный скрипт на удаленных компьютерах, используйте Параметр
FilePath
вInvoke-Command
.Например, следующая команда запускает скрипт
Sample.ps1
на компьютерахS1
иS2
:invoke-command -computername S1, S2 -filepath C:\Test\Sample.ps1
Результаты сценария возвращаются на локальный компьютер. Вы не нужно копировать какие-либо файлы.
Другие советы
Вот пример ...
Удаленный скрипт:
try {
... go do stuff ...
} catch {
return 1
exit
}
return 2
exit
Локальный скрипт:
function RunRemote {
param ([string]$remoteIp, [string]$localScriptName)
$res = Invoke-Command -computername $remoteIp -UseSSL -Credential $mycreds -SessionOption $so -FilePath $localScriptName
return $res
}
$status = RunRemote $ip_name ".\Scripts\myRemoteScript.ps1"
echo "Return status was $status"
$ so, -UseSSL и $ mycreds не нужны, если вы полностью в группе доверия. Кажется, это работает для меня ... удачи!
Если удаленный скрипт-блок возвращает код выхода, закрытие будет закрыто. Я просто проверяю состояние пессиона. Если он закрыт, я предполагаю ошибку. Отчасти хакерский, но он работает для моих целей.
$session = new-pssession $env:COMPUTERNAME
Invoke-Command -ScriptBlock {try { ErrorHere } Catch [system.exception] {exit 1}} -Session $session
if ($session.State -eq "Closed")
{
"Remote Script Errored out"
}
Remove-PSSession $session
$session = new-pssession $env:COMPUTERNAME
Invoke-Command -ScriptBlock {"no exitcodes here"} -Session $session
if ($session.State -ne "Closed")
{
"Remote Script ran succesfully"
}
Remove-PSSession $session
Я хотел перехватить возврат кода ошибки с помощью пакетного сценария, вызываемого через команду вызова.Это непростая задача, но я нашел хороший и простой способ ее выполнить.
Ваш сценарий PowerShell$res=invoke-command -Computername %computer% {C:\TEST\BATCH.CMD}
write-host $res
Вы обнаружите, что $res — это пакетный вывод. Зная это, можно использовать @echo off, >nul и echo «то, что вы хотите вернуть»!
Вы пакетный скрипт
@echo off
echo "Start Script, do not return" > nul
echo 2
Теперь $res будет = 2!Затем вы можете применить любую логику в своем пакете.
Вы даже можете использовать invoke-command -sjob использовать приемную работу, чтобы получить выход!В этом случае вам не нужно использовать $res.
Ура, Жюльен
Последняя приведенная ниже команда Powershell Invoke-Command возвращает логическое значение True, если код ошибки равен нулю из выполненного скрипта, и логическое значение False, если код возврата не равен нулю. Отлично работает для обнаружения кодов ошибок, возвращаемых из удаленного выполнения.
function executeScriptBlock($scriptString) {
Write-Host "executeScriptBlock($scriptString) - ENTRY"
$scriptBlock = [scriptblock]::Create($scriptString + " `n " + "return `$LASTEXITCODE")
Invoke-Command -Session $session -ScriptBlock $scriptBlock
$rtnCode = Invoke-Command -Session $session -ScriptBlock { $? }
if (!$rtnCode) {
Write-Host "executeScriptBlock - FAILED"
}
Else {
Write-Host "executeScriptBlock - SUCCESSFUL"
}
}
Если вам нужен вывод из блока скриптов и кода выхода, вы можете выбросить код выхода из блока и преобразовать его обратно в целое число на вызывающей стороне ...
$session = new-pssession $env:COMPUTERNAME
try {
Invoke-Command -ScriptBlock {Write-Host "This is output that should not be lost"; $exitCode = 99; throw $exitCode} -Session $session
} catch {
$exceptionExit = echo Если вам нужен вывод из блока скриптов и кода выхода, вы можете выбросить код выхода из блока и преобразовать его обратно в целое число на вызывающей стороне ...
This is output that should not be lost
$exceptionExit = 99
Возвращает стандартный выход и последний код выхода. Однако для этого требуется, чтобы в вашем блоке скрипта любые исключения перехватывались и перебрасывались как коды выхода. Вывод из примера ...
<*>.tostring()
[int]$exceptionExit = [convert]::ToInt32($exceptionExit)
Write-Host "`$exceptionExit = $exceptionExit"
}
Возвращает стандартный выход и последний код выхода. Однако для этого требуется, чтобы в вашем блоке скрипта любые исключения перехватывались и перебрасывались как коды выхода. Вывод из примера ...
<*>