перехватывать код возврата команды с помощью "invoke-command" - Powershell 2 - PullRequest
17 голосов
/ 31 июля 2009

Я использую "invoke-command" для выполнения скрипта на удаленной машине.

invoke-command -computername <server_name> -scriptblock {command to execute the script}

Мой скрипт возвращает «-1», если есть какие-либо ошибки. Итак, я хотел убедиться, что скрипт успешно выполнен, проверив код возврата.

Я пытался следующим образом.

$code = invoke-command -computername ....

Но это ничего не возвращает.

Разве Invoke-command не перехватывает код возврата блока скрипта?

Есть ли другой способ решить эту проблему?

Ответы [ 6 ]

10 голосов
/ 31 июля 2009

Я думаю, что если вы запустите команду таким образом на другом сервере, вы не сможете найти код возврата вашего скрипта. Это связано с тем, что 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

Результаты скрипта возвращаются на локальный компьютер. Вы не нужно копировать файлы.

3 голосов
/ 24 июня 2014

Если удаленный скрипт-блок возвращает код выхода, закрытие будет закрыто. Я просто проверяю состояние пессиона. Если он закрыт, я предполагаю ошибку. Отчасти хакерский, но он работает для моих целей.

$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
3 голосов
/ 08 сентября 2010

Вот пример ...

Удаленный скрипт:

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"

$ Итак, -UseSSL и $ mycreds не нужны, если вы полностью в группе доверия. Кажется, это работает для меня ... удачи!

0 голосов
/ 14 мая 2018

Последняя приведенная ниже команда 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"
    }
}
0 голосов
/ 22 мая 2017

Если вам нужен вывод из блока скрипта и кода выхода, вы можете выбросить код выхода из блока и преобразовать его обратно в целое число на вызывающей стороне ...

$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 $_.tostring()
    [int]$exceptionExit = [convert]::ToInt32($exceptionExit)
    Write-Host "`$exceptionExit = $exceptionExit"
}

Возвращает стандартный выход и последний код выхода. Однако для этого требуется, чтобы в вашем блоке скрипта любые исключения перехватывались и перекидывались как коды выхода. Вывод из примера ...

This is output that should not be lost
$exceptionExit = 99
0 голосов
/ 26 января 2016

Я искал код ошибки, возвращаемый пакетным скриптом, вызываемым через invoke-command. Задача не из легких, но я нашел хороший и простой способ сделать это.

Ваш скрипт 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 -AsJob Используйте Receive-job, чтобы получить результат! В этом случае вам не нужно использовать $ res.

Cheers, Julien

...