【问题标题】:Speed up powershell command when using calculated properties使用计算属性时加速 powershell 命令
【发布时间】:2021-07-19 09:24:57
【问题描述】:

所以我想得到一个powershell命令来列出防火墙规则和端口,我基本上必须使用2个命令:Get-NetFirewallRuleGet-NetFirewallPortFilter

所以我基本上想出了这个:

Get-NetFirewallPortFilter | where-object {$_.LocalPort -cmatch '[0-9]+'}|select-object -Property @{n='Name';e={($_ | Get-NetFirewallRule).Name}}, @{n='Description';e={($_ | Get-NetFirewallRule).description}}, Protocol, LocalPort, RemotePort, @{n='Direction';e={($_|Get-NetFirewallRule).Direction}}

我首先选择了Get-NetFirewallPortFilter,因为我只想获得数字端口(因此我不想获得“任何”)。

问题是,我拥有的计算属性越多,运行速度就越慢。它每秒生成 3 行,IMO 非常慢。

我对命令进行了计时以查看需要多长时间(Out-GridView 也看到了输出,我认为它不会增加太多时间,它似乎每秒生成的行数一样多) :

PS C:\> measure-command { Get-NetFirewallPortFilter | where-object {$_.LocalPort -cmatch '[0-9]+'}|select-object -Property @{n='Name';e={($_ | Get-NetFirewallRule).Name}}, @{n='Description';e={($_ | Get-NetFirewallRule).description}}, Protocol, LocalPort, RemotePort, @{n='Direction';e={($_|Get-NetFirewallRule).Direction}} |out-gridview }


Days              : 0
Hours             : 0
Minutes           : 1
Seconds           : 59
Milliseconds      : 143
Ticks             : 1191434968
TotalDays         : 0.00137897565740741
TotalHours        : 0.0330954157777778
TotalMinutes      : 1.98572494666667
TotalSeconds      : 119.1434968
TotalMilliseconds : 119143.4968

它在约 119 秒内输出 358 行。

我可以运行任何优化以使其运行更快吗?

【问题讨论】:

  • 为什么要在一行中按所有内容? Get-NetFirewallRule 显然是一个昂贵的 cmdlet。因此,将结果保存在变量 ($FirewallRule = $_ |Get-NetFirewallRule) 中并(重新)在计算表达式中使用该变量。
  • @iRon 但是我该怎么做呢?如果我声明一个变量然后像什么都没发生一样继续前进,它不会破坏管道吗?我的意思是,我不知道如何在命令行上构造它,我在哪里声明变量?我在哪里使用命令分隔符 ;

标签: powershell optimization


【解决方案1】:

您在代码中多次使用 Get-NetFirewallRule,而每个 PortFilter 只能执行一次:

Get-NetFirewallPortFilter | Where-Object {$_.LocalPort -match '[0-9]+'} | ForEach-Object {
    $rule = $_ | Get-NetFirewallRule
    $_ | Select-Object @{Name = 'Name'; Expression = {$rule.Name}},
                       @{Name = 'Description'; Expression = {$rule.Description}},
                       Protocol, LocalPort, RemotePort, 
                       @{Name = 'Direction'; Expression = {$rule.Direction}}
} | Out-GridView

如果您取出 ForEach-Object 并改用 foreach() 可能会快一点:

$portFilters = Get-NetFirewallPortFilter | Where-Object {$_.LocalPort -match '[0-9]+'}
$result = foreach ($filter in $portFilters) {
    $rule = $filter | Get-NetFirewallRule
    $filter | Select-Object @{Name = 'Name'; Expression = {$rule.Name}},
                            @{Name = 'Description'; Expression = {$rule.Description}},
                            Protocol, LocalPort, RemotePort, 
                            @{Name = 'Direction'; Expression = {$rule.Direction}}
}
$result | Out-GridView

【讨论】:

  • 谢谢,这将时间降低到 39 秒,但这仍然不是我所说的“快速”,而且它肯定不如在 linux 上运行的快
  • @Lhakryma,你在 Linux 上使用 Powershell 吗?
  • 哦,不,我的意思是做相对相同的事情,但在 linux 上,会运行得更快。
  • 然后去用Linux?每个工具都有优点和缺点。如果你为了速度而使用 powershell,我认为你被误导了。
  • @DougMaure 我来到 powershell 不知道会发生什么。我只是在这里考虑效率,不要拍我哈哈
【解决方案2】:

向左过滤总是最快的,首先是 get-netfirewallportfilter。这大约需要 18 秒。我在使用 -pipelinevariable(或 -pv)和 get-netfirewallportfilter 时遇到了问题。 Powershell 命令操作对象与 linux 命令操作文本。

编辑:管道到 get-netfirewallrule 的行为很奇怪,就像所有对象都会一次性处理。我把它放在一个 foreach 对象中。我将名称更改为显示名称并将描述放在最后。

# not work
Get-NetFirewallPortFilter -pipelinevariable port
Get-NetFirewallPortFilter : Cannot retrieve the dynamic parameters for the cmdlet. Object reference not set to an
instance of an object.
At line:1 char:1
+ Get-NetFirewallPortFilter -pipelinevariable port
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-NetFirewallPortFilter], ParameterBindingException
    + FullyQualifiedErrorId : GetDynamicParametersException,Get-NetFirewallPortFilter
Get-NetFirewallPortFilter |
where localPort -match \d -pipelinevariable port |
% { $_ | Get-NetFirewallRule } | select displayname,
@{n='Protocol';  e={$port.protocol}},
@{n='Localport'; e={$port.localport}},
@{n='Remoteport';e={$port.remoteport}},
direction, description | ft
DisplayName                    Protocol Localport Remoteport Direction description
-----------                    -------- --------- ---------- --------- -----------
SNMP Trap Service (UDP In)     UDP      162       Any          Inbound Inbound rule for the SNMP Trap Service to allow SNMP traps. [UDP 162]
SNMP Trap Service (UDP In)     UDP      162       Any          Inbound Inbound rule for the SNMP Trap Service to allow SNMP traps. [UDP 162]
Delivery Optimization (TCP-In) TCP      7680      Any          Inbound Inbound rule to allow Delivery Optimization to connect to remote endpoints

【讨论】:

  • 由于某种原因,您的最后一条命令仅返回本地端口为 53 的规则。
猜你喜欢
  • 1970-01-01
  • 2015-10-01
  • 1970-01-01
  • 2017-05-12
  • 1970-01-01
  • 2021-03-06
  • 1970-01-01
  • 1970-01-01
  • 2019-07-28
相关资源
最近更新 更多