powershell 有什么方法可以改变我的脚本,使其更快地执行功能?

nc1teljy  于 2024-01-08  发布在  Shell
关注(0)|答案(2)|浏览(134)

我有一个简单的脚本,它导入一个计算机名称列表,从列表中ping每台计算机,看看它是否在线。如果它在线,它从工作站请求几行信息。我每周运行一次这个脚本,但它需要几个小时才能完成....它一次在每台计算机上执行1个操作......好奇我是否可以将它更改为在多台计算机上执行相同的操作,或者所有的人都在同一时间。

$localComputer = "MyComputerName"
$computer = Import-Csv "\\$localComputer\path\computers.csv"
$outArray = @()

foreach ($computer in $computer) {
    $pingTest = Test-Connection $computer $computer.name -Count 1 -Quiet

    if ($pingTest -eq $false) {
        Write-Host $computer.name -ForgroundColor Red

        $outArray += New-Object PSobject -Property @{
            'computer' = $computer.name
            'ping' = "Offline"
            'model' = "N/A"
            'serviceTag' = "N/A"
            'osVersion' = "N/A"
        }
    
    }
    
    else {
        Write-Host $computer.name -ForegroundColor Green
        Get-Service -ComputerName $computer.name -name winrm | Restart-Service 
        start-sleep -s 1
        $modelInfo = Invoke-Command -ComputerName $computer.name -ScriptBlock {Get-wmiobject win32_computersystem}
        $serviceTag = Invoke-Command -ComputerName $computer.name -ScriptBlock {Get-wmiobject win32_bios}
        $osVersion = Invoke-Command -ComputerName $computer.name -ScriptBlock {Get-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion"}

        $outArray += New-Object PSobject -Property @{
            'computer' = $computer.name
            'ping' = "Online"
            'model' = $modelInfo.Model
            'serviceTag' = $serviceTag.SerialNumber
            'osVersion' = $osVersion.DisplayVersion
        }
    
    }
}

$outArray | Select-Object 'computer','serviceTag','model','osVersion','ping' | Export-Csv "\\$localComputer\path\results.csv" -NoTypeInformation

字符串

11dmarpk

11dmarpk1#

所以,有一些事情可能会有所帮助,

  • 压缩
$pingTest = Test-Connection $computer $computer.name -Count 1 -Quiet
if ($pingTest -eq $false) {

字符串
进入if ($false -eq Test-Connection $computer $computer.name -Count 1 -Quiet ) {

记住:比较值应该总是在左边,因为它决定了比较中的类型。这是一个好习惯,因为你永远不知道它什么时候会导致问题,特别是在比较$false,$null和空值时

  • 为什么是Restart-ServiceStart-Sleep
  • 使用列表和Foreach-Object -Parallel

使用-Parallel标志,Foreach-Object将同时处理集合中的多个项(在本例中为计算机)。
使用List可以让你使用.Add()方法,它比+=更有效,因为它不会破坏和重新创建集合,而只是添加新元素。特别是因为我认为你不关心元素添加的顺序(如果你关心,只需添加一个时间戳属性,这样你就可以对它们进行排序)

PS > $outArray = [system.collections.generic.list[pscustomobject]]::New()

PS > @(1;2;3) | ForEach-Object -Parallel { 
       $temp = $using:outArray # this associates the $outArray variable that exist outside the scope of the Loop with the $temp variable that exists only in each loop independently
       $temp.add([pscustomobject]@{a=$_; b="zio_$_"}) 
   }

PS > $outVariable

     a  b
     -  -
     1  zio_1
     2  zio_2
     3  zio_3

dxxyhpgq

dxxyhpgq2#

我会这样做,并行地做事情,避免任何类型的数组复制与“+="。test-connection有一些恼人的头名和属性名之间的不一致。起初,我试图用invoke-command尝试try/catch,但我没有得到它的工作。powershell 5.1 test-connection only。& { }或$()可能在这里工作得很好。

$computers = Import-Csv computers.csv | % name

$pingTest = Test-Connection $computers -AsJob -count 1 |
  receive-job -wait -AutoRemoveJob
$up = $pingtest | ? responsetime | % address
$down = $pingtest | ? { -not $_.responsetime } | % address

& { 
  $down | foreach-object {
    [pscustomobject]@{
      pscomputername = $_
      ping = 'Offline'
      model = 'N/A'
      serviceTag = 'N/A'
      osVersion = 'N/A'
    }
  }
  
  invoke-command $up {
    [pscustomobject]@{
      ping = 'Online'
      model = Get-wmiobject win32_computersystem | % Model
      serviceTag = Get-wmiobject win32_bios | % SerialNumber
      osVersion =
        Get-ItemProperty 'HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion' |
        % DisplayVersion
    }
  }
} | Export-Csv results.csv -NoTypeInformation

个字符

相关问题