使用 powershell,我计划在远程主机上运行许多功能来收集信息。
下面是一个远程检索文件内容的示例,只需运行名为 getcontentfile 的函数并以远程主机的名称为参数:
function getcontentfile
{
[CmdletBinding()]
param($hostname)
$info = Get-Content "C:\fileinfo.xml"
write-host $info
}
此函数应将有关远程主机的信息返回到 PowerShell 的本地实例。我该如何修改此脚本来实现这一点?
答案1
首先,不要使用返回信息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
将返回作业对象,然后可以使用 cmdlet 分别进行查询Job
(请参阅gcm -noun job
列表,注意Receive-Job
获取作业的结果)。
答案2
您可以在远程机器上运行本地加载的函数:
Invoke-Command -ComputerName Comp1 -cred $cred -ScriptBlock ${function:get-contentfile } -argumentlist "ParameterA", "ParameterB"
答案3
你的第一个选择是启用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
答案4
简短的回答是:你不能。
通常,您使用Invoke-Command
在远程计算机上运行命令。该命令可以是脚本块或 PowerShell 脚本。这两种方法都无法使用本地计算机上存在的变量或函数,也就是说,您无法提前加载函数以使其在远程计算机上可访问。
您需要做的是将它们放在远程计算机上,然后从那里加载它们。我们创建一个公共共享并将我们的 PowerShell 脚本部署到该共享。