Como posso executar uma função do PowerShell remotamente?

7

Usando o powershell, planejo executar muitas funções em um host remoto para coletar informações.

Aqui está um exemplo para recuperar o conteúdo do arquivo remotamente apenas executando uma função chamada getcontentfile com o parâmetro como o nome do host remoto:

function getcontentfile 
{
    [CmdletBinding()]
    param($hostname)
    $info = Get-Content "C:\fileinfo.xml"
    write-host $info
}

Essa função deve retornar informações sobre o host remoto para a instância local do PowerShell. Como posso modificar esse script para fazer isso?

    
por Aimar 09.07.2012 / 15:08

4 respostas

4

Primeiramente, para retornar informações, não use Write-Host (isso é verdade sempre, a menos que você queira apenas que ambas as cores e operem interativamente localmente).

Faça da saída o valor de retorno da função:

function getcontentfile 
{
    [CmdletBinding()]
    param($hostname)
    $info = Get-Content "C:\fileinfo.xml"
    $info
}

Em segundo lugar: ative a comunicação remota de PSH nos sistemas de destino: consulte a ajuda para Enable-PSRemoting .

Em terceiro lugar: execute o comando remotamente:

Invoke-Command -computer comp1,comp2 -ScriptBlock { Get-Content "C:\fileinfo.xml"  }

Isso retornará o conteúdo do arquivo nos dois computadores para separar os resultados. A adição de -AsJob retornará objetos de trabalho que podem ser consultados separadamente com os cmdlets Job (consulte gcm -noun job para uma lista, observe Receive-Job para obter os resultados de um trabalho).

    
por 09.07.2012 / 15:56
4

Você pode executar uma função carregada local em um computador remoto:

Invoke-Command -ComputerName Comp1 -cred $cred -ScriptBlock ${function:get-contentfile } -argumentlist "ParameterA", "ParameterB"
    
por 13.07.2012 / 08:14
3

Sua primeira opção é habilitar Powershell 2.0 Remoting .

Pessoalmente, eu não era muito interessante no remoting embora fosse poderoso, então escrevi um script para usar o WMI, criei um processo com o cmd.exe e depois canalize o stdout e o stderr para um arquivo de log que você pode ler .

O script deixa seu arquivo de log no computador remoto, então você pode simplesmente: get-content \remotecomputer\c$\remoteExec.log para lê-lo.

<#
.SYNOPSIS
    Remotely executes a command and logs the stdout and stderr to a file on the
    remote computer.
.DESCRIPTION
    This script accepts three parameters (one optional) and executes a program on
    a remote computer.  It will verify connectivity and optionally (verifyPath) the
    existence of the program to be executed.  If either verifications fail, it will
    not attempt to create the process on the remote computer.
.EXAMPLE
    .\remoteExec.ps1 -program "dir" -args "c:\" -computerName "SEANC"
.EXAMPLE
    .\remoteExec "C:\Windows\SysWOW64\msiexec.exe" "/i c:\a.msi /passive /log c:\a-install.log" SEANC C:\Windows\Temp\remote.log -verifyPath
.PARAMETER computerName
    The name of the computer on which to create the process.
.PARAMETER program
    The command to run on the remote computer.
.PARAMETER args
    The command arguments.
.PARAMETER log
    The file to which the stderr and stdout generated by the command will be redirected.
    This is a local path on the remote computer.
.PARAMETER verifyPath
    Switch to enforce path verification.
#>
param(
    [parameter(Mandatory=$true)] [string]$program,
    [parameter(Mandatory=$false)][string]$args = "",
    [parameter(Mandatory=$true)] [string]$computerName,
    [parameter(Mandatory=$false)][string]$log = "C:\remoteExec.log",
    [parameter(Mandatory=$false)][switch]$verifyPath = $false
)

if (-not (Test-Connection $computerName -Quiet -Count 1))
{
    return Write-Error "Unable to connect to $computerName."
}

if ($verifyPath -and (-not (Test-Path \$computerName\$($program.replace(":","$")) -PathType Leaf))) {
    return Write-Error "Path $program does not exist on $computerName."
}

try {
    $remoteWmiProcess = [wmiclass]"\$computerName\root\cimv2:win32_process"
    $remoteProcess = $remoteWmiProcess.create(
        "cmd.exe /c '"$program $args > $log 2>&1'""
    )
} catch {
    return Write-Error ("Unable to create process through WMI.");
}

if ($remoteProcess.returnValue -ne 0) {
    return Write-Error ("FAILED on $computerName with return code: " + $remoteProcess.returnValue)
} else {
    return ("Successful trigger on $computerName; returned: " + $remoteProcess.returnValue)
}

EDIT: Neste exemplo, o script é chamado remoteExec.ps1 e eu o uso para criar um processo de powershell remoto e executar um comando (o que o asker está tentando fazer):

.\remoteExec.ps1 -program "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -verifyPath -computerName "computer1" -args "-command Get-ChildItem C:\"

Eu poderia ler o log com:

Get-Content \computer1\C$\remoteExec.log

    
por 09.07.2012 / 15:19
0

A resposta curta é que você não pode.

Normalmente, você usa Invoke-Command para executar um comando em um computador remoto. Esse comando pode ser um bloco de script ou um script do PowerShell. Nenhuma dessas abordagens pode alcançar e usar variáveis ou funções que existem em seu computador local, ou seja, você não pode carregar suas funções com antecedência para torná-las acessíveis no computador remoto.

O que você precisa fazer é obtê-los no computador remoto e, em seguida, carregá-los de lá. Criamos um compartilhamento comum e implantamos nossos scripts do PowerShell nesse compartilhamento.

    
por 11.07.2012 / 03:05