如何解决PsExec 仅返回 BackgroundJob
我遇到了 PsExec 的标准输出在 BackgroundJob 中不同的问题。
关于我工作环境的一些信息:
我有大量没有 WinRM 的 Windows XP 计算机,我无法使用 WMI 调用,但是 PsExec 可以工作。我需要从所有 XP 机器上获取命令的标准输出。我能够在 BackgroundJob 之外获得我期望的标准输出,但是当我尝试在 BackgroundJob 内部执行 PsExec 时,我只收到标准输出的第一行。
以下是我看到的差异示例:
# 1.2.3.4 = IP Address of an XP Machines
# 123.123.123.123 = IP of a server I want to compare the time against.
$output = & "path\to\psexec\psexec.exe" "\\1.2.3.4" -accepteula -u "$($creds.Username)" -p "$($creds.GetNetworkCredential().Password)" w32tm /stripchart /computer:123.123.123.123 /samples:1 /dataonly
Write-Host $output
此代码输出:Tracking 123.123.123.123 [123.123.123.123]. Collecting 1 samples. The current time is 6/30/2021 2:41:51 PM (local time). 14:41:51,+00.0059682s
然而,这段代码输出了一些不同的东西:
Start-Job -Name "1.2.3.4" -ScriptBlock {
# 1.2.3.4 = IP Address of an XP Machines
# 123.123.123.123 = IP of a server I want to compare the time against.
$output = & "path\to\psexec\psexec.exe" "\\1.2.3.4" -accepteula -u "$($using:creds.Username)" -p "$($using:creds.GetNetworkCredential().Password)" w32tm /stripchart /computer:123.123.123.123 /samples:1 /dataonly
return $output
}
$returnValue = Get-Job "1.2.3.4" | Receive-Job -Wait -AutoRemoveJob
Write-Host $returnValue
这输出:Tracking 123.123.123.123 [123.123.123.123].
这是 w32tm /stripchart /computer:123.123.123.123 /samples:1 /dataonly
的标准输出的第一行。
我做错了吗?我的理解是,BackgroundJob 内部和外部的标准输出不应该有区别。
我对 PowerShell 比较陌生。如果我的理解有误,请赐教。您能给我的任何信息或建议都会有所帮助。
谢谢!
更新:在阅读完 Iconiu 对此StackOverflow Thread的回答后
这似乎是 PowerShell 的限制。我目前正在为此制定解决方法。当我有工作时,我会再次更新问题。
更新 2:我找到了适合我的目的的解决方法,我想我会分享它。
$ip = '1.2.3.4' # IP of an XP Machine
$otherip = '123.123.123.123' # Machine I want use for w32tm
# Create the temp Folder outside of the job if it does not exist.
if(!(Test-Path "\\$ip\c`$\temp\")) {
MKDIR "\\$ip\c`$\temp\"
Start-Sleep -Seconds 1 # Sleep for one second to allow for network lag.
}
Start-Job -Name $ip -ScriptBlock {
$ip = $using:ip
$otherip = $using:otherip
$creds = $using:creds
& "path\to\psexec\psexec.exe" \\$ip -accepteula -u $creds.Username -p $creds.GetNetworkCredential().Password cmd /c "w32tm /stripchart /computer:$otherip /samples:1 /dataonly > C:\temp\w32tmstripchart.txt"
if(Test-Path "\\$ip\c`$\temp\w32tmstripchart.txt") {
$stdout = Get-Content -Path "\\$ip\c`$\temp\w32tmstripchart.txt" -Raw
return $stdout
} else {
return "ERROR"
}
$retVal = Get-Job -Name $ip | Receieve-Job -Wait -AutoRemoveJob
Write-Host $retVal
如果您想从命令中捕获 stderr 和 stdout,请在将输出定向到文件后添加 2>&1
。例如,w32tm /stripchart /computer:123.123.123.123 /samples:1 /dataonly > w32tmstripchart.txt 2>&1
如果您希望标准输出是字符串数组而不是单个字符串,请从 -Raw
命令中删除 Get-Content
开关。
希望对以后遇到类似问题的人有所帮助。
解决方法
确实,Start-Job
报告仅来自psexec
输出的第一 stdout 行似乎存在问题强>.
- 我鼓励您在 PowerShell (Core) GitHub repo 报告此问题,该问题在 PowerShell Core 7.2.0-preview.7 中仍然存在。
Start-Job
创建基于子进程的后台作业,但是有一个更轻量级、通常更可取的基于线程的替代方案,{ {3}},没有有同样的问题。
-
Start-ThreadJob
附带 PowerShell (Core) v6+,并且可以在Windows PowerShell v3+ 中按需安装 - 请参阅{ {3}}。
因此,请尝试以下使用 Start-ThreadJob
的方法:
Start-ThreadJob -Name 1.2.3.4 -ScriptBlock {
& 'path\to\psexec\psexec.exe' -nobanner \\1.2.3.4 -accepteula -u $using:creds.Username -p ($using:creds).GetNetworkCredential().Password w32tm /stripchart /computer:123.123.123.123 /samples:1 /dataonly 2>$null
}
如果您还想捕获 w32tm
的 stderr 输出:
Start-ThreadJob -Name 1.2.3.4 -ScriptBlock {
& 'path\to\psexec\psexec.exe' -nobanner \\1.2.3.4 -accepteula -u $using:creds.Username -p ($using:creds).GetNetworkCredential().Password cmd /c 'w32tm /stripchart /computer:123.123.123.123 /samples:1 /dataonly 2>&1' 2>$null
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。