使用类似 unix 的管道语法运行 powershell 脚本或函数

使用类似 unix 的管道语法运行 powershell 脚本或函数

我想使用 powershell 中的管道运行多个自定义处理步骤。

在 Linux 中我可以做这样的事情:

listServers.sh | <some commands to filter servers> | commandToApplyToEachServer.sh

并将与每个步骤相关的代码放在不同的脚本中(每个命令可以采用多个参数,并且至少最后一个参数可以完全由不同的脚本替换)

我想在 powershell 中做一些类似的事情,而不增加任何“开销”(必须在使用其功能之前获取脚本源,如果有更改则必须重新获取脚本源等)

直接在提示符下运行命令很容易:

"server1","server2" | % {Get-Service -Name myservicename -ComputerName $_ | Set-Service -Status Stopped }

...但我想让用户(和我自己)能够以更简单、更强大的方式执行此命令和类似的命令(基本上将每个步骤包装在脚本或函数中,无论哪种最强大的方式)。

我最接近的答案是:

[CmdletBinding()]
param(
    [Parameter(Mandatory=$true)]
    $env
)

Function global:srv {
  Begin {
  }

  Process {
    Get-Service -Name someServiceName -ComputerName $_
  }

  End {
  }
}

Get-Content "$env.csv"

这使我可以运行如下操作:

.\listServers.ps1 appServers | srv

但不幸的是,srv 函数仅在整个命令运行完成后才会更新(因此对 echo-pipe 函数的任何更改都要等到我第二次运行它时才会生效,当然我需要先获取 listServers.ps1 才能执行任何操作,因为 srv 在此之前不存在)

更新:我已开始使用单脚本方法(使用一些参数来处理过滤并控制最终要执行的命令,而不是使用管道)。但如果可以使用管道,那么了解它仍然很有趣。

答案1

似乎最直译的是

listServers.sh | <some commands to filter servers> | commandToApplyToEachServer.sh

就像:

Get-content listServers.txt | Where-Object {*attributes and whatever} | CommandToRun

使用 PowerShell 和管道,您可以自行决定如何获取任何内容并将其传输出去。例如,假设我想重新启动所有名为 MAILSERVERxxxx 的服务器:

Get-QADComputer -name * | where-object {$_.Name -Match "$MAILSERVER"} | Restart-Computer -ComputerName $_.Name

可以做到,但更符合 PowerShell 实践的是,你通常可以用非常不同的方式来处理这个问题:

Get-QADComputer -Name "MAILSERVER*" | Restart-Computer $_.Name

几点说明:

  • PowerShell 非常灵活
  • PowerShell 旨在将 Windows 命令行提升到 BASH 级别的实用性
  • 语法也很灵活
  • Get-QADComputers 是 Quest 和 Dell 的 cmdlet

您还可以使用类似 C 的语法来执行许多相同的操作,这进一步扩展了 PowerShell 的功能。

例如,如果您想要读取一个文件,则根据匹配条件构建和排列,然后在继续之前执行一些操作:

$someArray = @()
Get-Content "H:\SomeFile.txt" | `
Foreach-object {
 if ($_ -MAtch "$MAILSERVER") { $someArray += $_}
 }

$someArray | foreach-Object {
  if (Test-Connection "$_") {
    $Version = (Get-WmiObject -ComputerName "$_" -Class "Win32_OperatingSystem").Version
  }
}

我希望这有帮助。

答案2

Get-Content 'ComputerNames.txt' | Restart-Computer

完成。这将从文件中读取行,并将每行传递到管道。Restart-Computer可以从管道中获取一个字符串作为参数ComputerName,这就是它的工作原理。

如果您想在每次重启之前确认名称,请添加-ConfirmRestart-Computer

相关内容