Используя powershell, я планирую запускать множество функций на удаленном хосте для сбора информации.
Вот пример удаленного получения содержимого файла, просто запустив функцию getcontentfile с параметром в качестве имени удаленного хоста:
function getcontentfile
{
[CmdletBinding()]
param($hostname)
$info = Get-Content "C:\fileinfo.xml"
write-host $info
}
Эта функция должна возвращать информацию об удаленном узле в локальный экземпляр PowerShell. Как я могу изменить этот скрипт для этого?
Вы можете запустить локально загруженную функцию на удаленном компьютере:
Invoke-Command -ComputerName Comp1 -cred $cred -ScriptBlock ${function:get-contentfile } -argumentlist "ParameterA", "ParameterB"
Во-первых, чтобы вернуть информацию, не используйте Write-Host
(это верно всегда, если вы действительно не хотите, чтобы у обоих были цвета и работать только локально в интерактивном режиме).
Сделайте вывод возвращаемым значением функции:
function getcontentfile
{
[CmdletBinding()]
param($hostname)
$info = Get-Content "C:\fileinfo.xml"
$info
}
Во-вторых: включите удаленное взаимодействие PSH на целевых системах: см. Помогите для Enable-PSRemoting
.
В-третьих: запустить команду удаленно:
Invoke-Command -computer comp1,comp2 -ScriptBlock { Get-Content "C:\fileinfo.xml" }
Это вернет содержимое файла на два компьютера, чтобы разделить результаты, добавив -AsJob
вернет объекты задания, которые затем можно запросить отдельно с Job
командлеты (см. gcm -noun job
для списка обратите внимание Receive-Job
чтобы получить результаты работы).
Ваш первый вариант - включить Удаленное взаимодействие Powershell 2.0.
Лично мне было неинтересно удаленное взаимодействие, хотя оно мощно, поэтому я написал сценарий для использования WMI, создал процесс с помощью cmd.exe, а затем перенаправил stdout и stderr в файл журнала, который затем можно было прочитать.
Сценарий оставляет свой файл журнала на удаленном компьютере, поэтому вы можете просто: get-content \\remotecomputer\c$\remoteExec.log
прочитать это.
<#
.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)
}
РЕДАКТИРОВАТЬ: В этом примере сценарий называется remoteExec.ps1, и я использую его для создания удаленного процесса PowerShell и запуска команды (что пытается сделать запрашивающий):
.\remoteExec.ps1 -program "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -verifyPath -computerName "computer1" -args "-command Get-ChildItem C:\"
Затем я мог прочитать журнал с помощью:
Get-Content \\computer1\C$\remoteExec.log
Короткий ответ: вы не можете.
Обычно вы используете Invoke-Command
для выполнения команды на удаленном компьютере. Эта команда может быть блоком сценария или сценарием PowerShell. Ни один из этих подходов не может использовать переменные или функции, существующие на вашем локальном компьютере, и использовать их, то есть вы не можете заранее загрузить свои функции, чтобы сделать их доступными на удаленном компьютере.
Все, что вам нужно сделать, это получить их на удаленном компьютере, а затем загрузить оттуда. Мы создаем общий ресурс и развертываем на нем сценарии PowerShell.