这里是一个示例,我有一个名为“ s1”的远程服务器,我想杀死其中的calc,记事本和winword进程。
我可能有两种方法可以做到这一点,
Get-Process -computername s1 -name "calc", "notepad", "winword" | Stop-Process
$processes = Get-Process -computername s1 -name "calc", "notepad", "winword"
Stop-Process -InputObject $processes
IMO,我认为第二种方法比第一种更好。
据说PowerShell中的管道实际上将对象一一传递给以下Cmdlet。在这种情况下,停止进程需要多次与远程计算机“ s1”进行通信,并逐个杀死这些进程。
相比之下,第二种方式,我想Stop-Process只会与远程计算机“ s1”通信,一次并一次完成操作。
我理解正确吗?
谢谢
马丁
答案 0 :(得分:2)
关于远程方面:
您应该完全选择其他方法:使用Invoke-Command
远程运行整个管道:
Invoke-Command -ComputerName s1 {
Get-Process -Name 'calc', 'notepad', 'winword' | Stop-Process
}
但是请注意,Invoke-Command
(PSv3 +)要求在目标计算机上配置 PowerShell远程处理(请参阅Get-Help about_Remote_FAQ
),而Get-Process
cmdlet使用远程处理的另一种过时形式。
实际上,当我在两台v5.1机器之间尝试您的方法时,本地运行的Stop-Process
命令试图对远程过程对象失败进行操作,并出现以下错误:< / p>
Cannot stop process "<name>" because of the following error:
Feature is not supported for remote machines.
通常,最好的方法是尽可能远地执行尽可能多的处理,并将结果仅传输到本地计算机。
关于管道输入与通过-InputObject
进行输入的更一般方面:
使用-InputObject
传递集合(Get-Foo -InputObject $collection
)肯定比通过管道($collection | Get-Foo
)发送该集合要快,但请注意需要将整个输入集合整体加载到内存中 , ,这有可能抵消管道的一项主要优势:内存限制
请注意,使用-InputObject
通常不是 管道输入的可行替代方法,因为许多cmdlet 不枚举集合您传递给-InputObject
(将1, 2 | ForEach-Object { "[$_]" }
与ForEach-Object { "[$_]" } -InputObject 1, 2
进行比较);通常,这是偶然发生的,它们使用不是{em> arrays 的-InputObject
声明,但有时是设计使然:Get-Member
cmdlet故意不枚举传递给{ {1}},因为它随后检查了集合的类型,而不是其元素的类型。有关背景信息,请参见this GitHub issue。
还请注意,如果还有其他流水线段(-InputObject
),则在输出上再次进行流式传输(一对一处理)。
您可以使用Get-Foo -InputObject ... | ...
语句 (foreach
)代替管道,从而加快逐项处理的速度,但是如果您可以避免在循环正文中调用cmdlet,则只有这样才有效。
但是,与foreach ($elem in $collection) { ... }
一样,此要求将整个输入集合整体加载到内存中 , >
使用Time-Command
,对10,000个输入对象(平均100次运行)进行性能比较:
-InputObject
示例计时(Windows 10上的Windows PowerShell 5.1,单核VM):
$collection = 1..10000
Time-Command -Count 100 { $collection | Write-Output },
{ Write-Output -InputObject $collection },
{ foreach ($o in $collection) { $o } }
Command Secs (100-run avg.) TimeSpan Factor
------- ------------------- -------- ------
foreach ($o in $collection) { $o } 0.010 00:00:00.0103421 1.00
Write-Output -InputObject $collection 0.015 00:00:00.0152200 1.47
$collection | Write-Output 0.108 00:00:00.1076183 10.41
是最快的(请注意循环主体中如何依赖 implicit 输出:如果使用了foreach
调用,那将是最慢的)解决方案),其性能{@ {1}}紧随其后;有趣的是,这些角色在PowerShell Core 中似乎是颠倒的。但是,请注意,这些因素会随输入集合(可能还有您的硬件)的大小而变化。