1

在运行 PowerShell v5 April preview 的机器上:

  • 尝试从 AD 获取服务器列表(是的,Windows 2003,它们需要消失!)并记下找到的服务器总数
  • Test-Connection对他们所有人并注意总响应
  • 在所有服务器上调用一个命令(需要不同的凭据)以运行一堆命令来收集有关每个服务器的信息并输出到它们上的文件
  • 创建新的 PSDrive 以映射到每个服务器以下载文件并记录下载的文件总数(即响应 ping 并成功调用命令/下载结果的服务器之间的差异)
  • 然后运行一个Get-Printers不会在 PowerShell v2 上运行的 cmdlet,并输出到与本地计算机上的下载结果相同的文件夹中的文件

我有一个工作脚本——它非常慢,我想学习和改进它,让它更快、更优雅。我发现很难把这些都写出来解释一下哈哈。如果你想解决这个问题,你会用什么方法来解决?

要开始制定更好的方法:

获取服务器列表并存储在变量中是可以的。

$2003s = Get-ADComputer -Filter {OperatingSystem -eq "Windows server 2003"} -Properties  OperatingSystem

合计一下就OK了。

$Total2003s = $2003s.count

现在可能有一些不再存在的 2003 服务器没有从 AD 中删除,所以让我们对它们进行 ping 操作。

$Responsive2003s = Test-Connection $2003s.dnshostname -Delay 1 -Count 1 -ErrorAction SilentlyContinue

如果说 2003 美元中有 300 个对象并且一半没有响应,这将永远存在。

Measure-Command {Test-Connection $2003s.dnshostname -Delay 1 -Count 1 -ErrorAction SilentlyContinue}

7分钟...

所以我想,嘿,让我们制作一个 Powershell 工作流,这样我就可以使用foreach -parallel. 如果我编写一个快速的工作流程来从 AD 和 foreach 获取服务器Test-Connection

Measure-Command {Workflow-Testconnection}

27 秒....

仅让这部分工作可以节省时间,但是我无法确定哪种方式来构建我的脚本/功能/工作流程或任何最有效的方式。

我想出了两个障碍。

  1. 在 ping 服务器的小型工作流程中,我无法(弄清楚如何)将结果存储在变量中以查看总数(使用$variable = Test-Connection ...Test-Connection | New-Variable,因此如果我看不到两者之间的差异,那么 ping 它们毫无意义广告中的服务器和响应的服务器。我可以使用

    $2003sDnsHostname | foreach {
      Get-Printer -ThrottleLimit 500 -ErrorAction SilentlyContinue -ComputerName $_ |
        Sort-Object -Property Portname |
        FT -AutoSize |  Out-File -FilePath "D:\$($_) - Printers.txt"
    }
    

    但它很慢,如果我使用更快的工作流程,我不能Format-TableGet-Printers.

  2. 我试图让整个事情成为foreach -parallel在所需位置使用的工作流程,但是因为我有一个$creds = Get-Crendential可以使用我Invoke-Command -Credential $Creds的工作流程甚至无法加载的工作流程。

似乎对于脚本的每一步我想要的每一个好处,都有一个破坏者使它不值得做,但我相信有一种方法:)

整个工作但缓慢的东西,经过编辑以删除敏感的东西等,只是为了得到这个概念。它可以做成一个带有参数和详细输出等的函数,但这也是一个待办事项。我想先看看能不能加速。

$SVRAcctCreds = Get-Credential

#Enable the ActiveDirectory module as first time users might not have it already on their computer, and it doesn't hurt to enable it again if it's already there
Enable-WindowsOptionalFeature -Online -FeatureName RemoteServerAdministrationTools-Roles-AD-Powershell -NoRestart

$2003s = Get-ADComputer -Filter {OperatingSystem -eq "Windows server 2003"} -Properties operatingsystem
$2003sDnsHostname = $2003s.dnshostname
$Total = $2003s.count
$Responsive2003s = Test-Connection $2003s.dnshostname -Delay 1 -Count 1 -ErrorAction SilentlyContinue
$TotalResponsive2003s = $Responsive2003s.count

Invoke-Command -ComputerName ($2003s.dnshostname) -Credential $SVRAcctCreds -ThrottleLimit 100 -ErrorAction SilentlyContinue -ScriptBlock {
  #Make folder for output
  mkdir Z:\2003Migration | Out-Null

  #Serial number, model number, output to file
  Get-WmiObject win32_computersystem |
    Select-Object Manufacturer, Model | Format-List |
    Out-File -Append -FilePath Z:\2003Migration\"$env:SiteCode $env:SiteName"_MigrationData.txt
  Get-WmiObject win32_bios | Select-Object SerialNumber |
    Out-File -Append -FilePath Z:\2003Migration\"$env:SiteCode $env:SiteName"_MigrationData.txt
  Systeminfo | Select-String "Install Date:" |
    Out-File -Append -FilePath Z:\2003Migration\"$env:SiteCode $env:SiteName"_MigrationData.txt
}

##### Download Gathered data from servers
$2003s | ForEach-Object {
  New-PSDrive -ErrorAction SilentlyContinue -PSProvider FileSystem -Name $_.name -Credential $SVRAcctCreds -Root "\\$($_.dnshostname)\z$\2003Migration"
} | Out-Null
Get-PSDrive | where name -Like "SVR*" | foreach {
  Copy-Item "$($_.Name):" -Recurse -Destination d:\ -ErrorAction SilentlyContinue
} 
$TotalPSDrives = (Get-PSDrive | where name -Like "SVR*").count

# Report other information

"Total number of servers on Windows Server 2003 in AD, matching by OperatingSystem " | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"$Total" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"

"Total Number of servers that responded to a ping command" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"$TotalResponsive2003s" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"

"Total Number of servers that ran the commands and returned data" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"Total Number of servers that ran the commands and returned data downloaded to D:\2003Migration"
"$TotalPSDrives " | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"$TotalPSDrives "
"Mismatch means server could be pinged but could not run a powershell session to invoke commands, possible hard drive full? Powershell remoting not enabled?"

####Printers
# Didn't have enough time to work out how to only ask responsive servers the printers, so ask all, takes longer, then clean up empty files
$2003sDnsHostname | foreach {
  Get-Printer -ThrottleLimit 500 -ErrorAction SilentlyContinue -ComputerName $_ |
    Sort-Object -Property Portname | FT -AutoSize |
    Out-File -FilePath "D:\2003Migration\$($_) - Printers.txt"
}
Get-ChildItem D:\2003Migration | where Length -EQ 0 | Remove-Item
#clean up text files left on server
Invoke-Command -ComputerName ($2003s.dnshostname) -Credential $SVRAcctCreds -ThrottleLimit 100 -ErrorAction SilentlyContinue -ScriptBlock {
  Remove-Item "Z:\2003migration" -Recurse -ErrorAction SilentlyContinue
}
4

1 回答 1

2

我总是发现工作流有点棘手,因为它们的行为与“常规”PowerShell 略有不同。相反,您可能不太难使用工作。像这样的东西会给你一个列表,其中只有那些响应的服务器的名称Test-Connection

$Responsive2003s = $2003s | % {
  Start-Job -ScriptBlock {
    Param($name, $address)
    if (Test-Connection $address -Delay 1 -Count 1 -EA SilentlyContinue) {
      $name
    }
  } -ArgumentList $_.Name, $_.IPv4Address
} | Wait-Job | Receive-Job
于 2015-06-20T11:12:52.513 回答