我想使用 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
,这就是它的工作原理。
如果您想在每次重启之前确认名称,请添加-Confirm
到Restart-Computer
。