【问题标题】:PowerShell Jobs vs Start-ProcessPowerShell 作业与启动进程
【发布时间】:2020-02-18 07:28:21
【问题描述】:

我制作了一个小诊断脚本,保存在我的$profile 中。在收集 CPU 名称时,我发现该命令大约需要 4 秒 (Get-WmiObject -Class Win32_Processor).Name。所以我想我会尝试 PowerShell Jobs,虽然我认为它们非常适合长时间的后台工作,但如果你只想在后台快速获取一小部分信息,初始化时间会很尴尬(比如 2-3 秒每个作业)所以我想我会使用 Start-Process 在我的脚本的其余部分运行时将值转储到临时文件中。我认为我这样做是正确的,但是如果您运行此函数 3 或 4 次,您会注意到 CPU 名称未填充。

• 像这样使用 Start-Process 是最优的吗,还是有人有更快的方法在后台并行启动小型作业?我知道有一种 .NET 方法可以做到这一点(但从我所看到的来看,它似乎超级复杂)?

• 你知道为什么我的“等待文件被创建并且在访问它之前非零”经常失败吗?

function sys {
    $System = get-wmiobject -class "Win32_ComputerSystem"
    $Mem = [math]::Ceiling($System.TotalPhysicalMemory / 1024 / 1024 / 1024)

    $wmi = gwmi -class Win32_OperatingSystem -computer "."
    $LBTime = $wmi.ConvertToDateTime($wmi.Lastbootuptime)
    [TimeSpan]$uptime = New-TimeSpan $LBTime $(get-date)
    $s = "" ; if ($uptime.Days -ne 1) {$s = "s"}
    $uptime_string = "$($uptime.days) day$s $($uptime.hours) hr $($uptime.minutes) min $($uptime.seconds) sec"

    $temp_cpu = "$($env:TEMP)\ps_temp_cpu.txt"
    $temp_cpu_cores = "$($env:TEMP)\ps_temp_cpu_cores.txt"
    $temp_cpu_logical = "$($env:TEMP)\ps_temp_cpu_logical.txt"
    rm -force $temp_cpu -EA silent ; rm -force $temp_cpu_cores -EA silent ; rm -force $temp_cpu_logical -EA silent
    Start-Process -NoNewWindow -FilePath "powershell.exe" -ArgumentList "-NoLogo -NoProfile (Get-WmiObject -Class Win32_Processor).Name > $temp_cpu"
    Start-Process -NoNewWindow -FilePath "powershell.exe" -ArgumentList "-NoLogo -NoProfile (Get-WmiObject -Class Win32_Processor).NumberOfCores > $temp_cpu_cores"
    Start-Process -NoNewWindow -FilePath "powershell.exe" -ArgumentList "-NoLogo -NoProfile (Get-WmiObject -Class Win32_Processor).NumberOfLogicalProcessors > $temp_cpu_logical"
    ""
    "Hostname:          $($System.Name)"
    "Domain:            $($System.Domain)"
    "PrimaryOwner:      $($System.PrimaryOwnerName)"
    "Make/Model:        $($System.Manufacturer) ($($System.Model))"  #     "ComputerModel:  $((Get-WmiObject -Class:Win32_ComputerSystem).Model)"
    "SerialNumber:      $((Get-WmiObject -Class:Win32_BIOS).SerialNumber)"
    "PowerShell:        $($PSVersionTable.PSVersion)"
    "Windows Version:   $($PSVersionTable.BuildVersion)"
    "Windows ReleaseId: $((Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'ReleaseId').ReleaseId)"
    "Display Card:      $((Get-WmiObject -Class:Win32_VideoController).Name)"
    "Display Driver:    $((Get-WmiObject -Class:Win32_VideoController).DriverVersion)"
    "Display ModelDesc: $((Get-WmiObject -Class:Win32_VideoController).VideoModeDescription)"
    "Last Boot Time:    $([Management.ManagementDateTimeConverter]::ToDateTime((Get-WmiObject Win32_OperatingSystem | select 'LastBootUpTime').LastBootUpTime))"   # $(wmic OS get LastBootupTime)
    "Uptime:            $uptime_string"
    # ipconfig | sls IPv4
    Get-Netipaddress | where AddressFamily -eq IPv4 | select IPAddress,InterfaceIndex,InterfaceAlias | sort InterfaceIndex

    # Get-PSDrive | sort -Descending Free | Format-Table
    # https://stackoverflow.com/questions/37154375/display-disk-size-and-freespace-in-gb
    # https://www.petri.com/checking-system-drive-free-space-with-wmi-and-powershell
    # https://www.oxfordsbsguy.com/2017/02/08/powershell-how-to-check-for-drives-with-less-than-10gb-of-free-diskspace/
    # Get-Volume | Where-Object {($_.SizeRemaining -lt 10000000000) -and ($_.DriveType -eq “FIXED”) -and ($_.FileSystemLabel -ne “System Reserved”)}
    gwmi win32_logicaldisk | Format-Table DeviceId, VolumeName, @{n="Size(GB)";e={[math]::Round($_.Size/1GB,2)}},@{n="Free(GB)";e={[math]::Round($_.FreeSpace/1GB,2)}}

    # Note: -EA silent on Get-Item otherwise get an error
    while (!(Test-Path $temp_cpu)) { while ((Get-Item $temp_cpu -EA silent).length -eq 0kb) { Start-Sleep -Milliseconds 500 } }
    "CPU:               $(cat $temp_cpu)"
    while (!(Test-Path $temp_cpu_cores)) { while ((Get-Item $temp_cpu_cores -EA silent).length -eq 0kb) { Start-Sleep -Milliseconds 500 } }
    "CPU Cores:         $(cat $temp_cpu_cores)"
    while (!(Test-Path $temp_cpu_logical)) { while ((Get-Item $temp_cpu_logical -EA silent).length -eq 0kb) { Start-Sleep -Milliseconds 500 } }
    "CPU Logical:       $(cat $temp_cpu_logical)"
    rm -force $temp_cpu -EA silent ; rm -force $temp_cpu_cores -EA silent ; rm -force $temp_cpu_logical -EA silent
    "Memory:            $(Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | Foreach {"{0:N2}" -f ([math]::round(($_.Sum / 1GB),2))}) GB"
    ""
    "Also note the 'Get-ComputerInfo' Cmdlet (has more info but slower to run)"
    ""
}

【问题讨论】:

    标签: powershell console


    【解决方案1】:

    要在 powershell 中后台运行作业,有以下 3 种方法来实现它

    1. Invoke-Command[3] -scriptblock { script } -asJob -computername localhost 2. Start-Job[2] -scriptblock { script } 3. Start-Process[1] powershell {script}

    如果您真的想在后台运行,每个作业彼此独立,您将不得不考虑使用第一个或第二个选项,因为它们都不需要输出到写入文件。

    Invoke-Command 启动与系统的新会话并在新实例中运行作业。

    Start-Job 在新的 powershell 实例下在后台创建一个新作业,需要更多时间来分配资源并启动进程。就像 start-process 一样,Start-Job 将在单独的 powershell.exe 实例中运行作业。

    Start-Process 要求您将标准输出重定向到文件[1]。您必须依赖磁盘的性能以及读写速度。您还必须确保不超过一个线程正在读取/写入此进程的输出。

    推荐 我发现 Invoke-Command 在运行 100 个并发作业以获取处理器信息时速度最快。此选项确实需要您提供 -ComputerName,然后您需要成为管理员才能使用 localhost 启动 winrm 会话。如果您在创建作业时不输出作业信息,则不会占用任何大量时间。

    Start-Job 和 Invoke-Command 都需要大约一秒钟来获取处理器信息,并且运行 100 个并发作业来获取相同的东西需要一些开销。

    $x = 0..100 | Invoke-Command -computername localhost -scriptblock { script } -asJob
    $x | % { $_ | wait-job | out-null }
    $output = $x | % { $_ | Receive-Job}
    # You can run measure-object, sort-object, etc as well
    

    [1]Start-Process

    RedirectStandardOutput:指定一个文件。此 cmdlet 将进程生成的输出发送到您指定的文件。输入路径和文件名。默认情况下,输出显示在控制台中。

    [2]Start-Job

    Start-Job cmdlet 在本地计算机上启动 PowerShell 后台作业。 ... PowerShell 后台作业在不与当前会话交互的情况下运行命令。

    [3]Invoke-Command

    Invoke-Command cmdlet 在本地或远程计算机上运行命令并返回命令的所有输出,包括错误。 ...要在后台作业中运行命令,请使用 AsJob 参数

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-04
      • 1970-01-01
      • 1970-01-01
      • 2013-03-15
      • 2011-04-27
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多