代码之家  ›  专栏  ›  技术社区  ›  YorSubs

PowerShell作业与启动过程

  •  0
  • YorSubs  · 技术社区  · 5 年前

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

    使用这样的启动过程是最佳的,还是有人有更快的方法在后台并行启动小任务?我知道有一个问题。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)"
        ""
    }
    
    0 回复  |  直到 5 年前
        1
  •  6
  •   Jawad user2418209    5 年前

    要在powershell的后台运行作业,有以下三种方法

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

    如果你真的想在后台运行,每个工作都是相互独立的,你必须考虑使用第一个或第二个选项,因为它们都不是 要求 要写入文件的输出。

    调用命令 启动与系统的新会话,并在新实例中运行作业。

    开始工作 在新的powershell实例下在后台创建一个新作业,分配资源和启动流程需要更多的时间。与启动流程一样,启动作业将在单独的powershell中运行作业。exe实例。

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

    正式建议 我发现 Invoke-Command 以最快的速度运行100个并发作业以获取处理器信息。此选项确实要求您提供-ComputerName,然后要求您作为管理员启动与localhost的winrm会话。如果在创建工作时不输出工作信息,则不会占用任何重要的时间。

    Start Job和Invoke命令都需要大约一秒钟的时间来获取处理器信息,而运行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

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

    [2] Start-Job

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

    [3] Invoke-Command

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

    推荐文章