2015-06-20 43 views
1

从一台计算机运行PowerShell的V5月预览:趁着:的foreach -parallel,调用命令,脚本构建

  • 试图获得的列表(是的,Windows 2003中,他们需要消失!)从AD服务器,并注意总服务器发现
  • Test-Connection他们所有,并注意总响应
  • 调用命令(这需要所有服务器上不同的凭据)运行一堆命令来收集信息有关每个服务器并输出到它们上面的文件
  • 创建新的PSDrives以映射到每个服务器以下载文件并记下下载的全部文件(即,区别服务器响应ping并成功调用命令/下载结果)
  • 然后运行一个Get-Printers cmdlet,它不会在PowerShell v2上运行,并输出到与下载结果相同的文件夹中的文件本地机器

我有一个工作脚本 - 它只是非常慢,我想学习和改进它,并使其更快,更优雅。我很难写出这一切,并解释哈哈。如果你正在努力解决这个问题,你会以什么方式解决它?

要开始工作了一个更好的办法:

获取服务器的列表,并储存在一个变量就可以了。

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

获得总就可以了。

$Total2003s = $2003s.count 

现在可能会有一些2003年的服务器再也不存在了,而这些服务器并没有从AD中删除,因此我们将它们全部ping通。

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

如果在$ 2003s中有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,所以没有点查验他们如果我看不到广告中的服务器和响应的服务器之间的差异。我可以用

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

    但它是缓慢的,如果我使用更快的工作流程,我不能对Get-Printers输出使用Format-Table

  2. 我试图让整个事情使用所需点foreach -parallel工作流,但因为我有一个$creds = Get-CrendentialInvoke-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 
} 

回答

1

我总是发现工作流有点棘手,因为它们的行为与“常规”PowerShell有微妙差别。用jobs代替你可能会有一些困难。这样的事情会给你一个名单只有那些回应的服务器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