Рабочие места PowerShell и Start-Process - PullRequest
1 голос
/ 16 февраля 2020

Я сделал небольшой сценарий диагностики c, который храню в своем $profile. При сборе имени процессора я обнаружил, что команда занимает около 4 секунд (Get-WmiObject -Class Win32_Processor).Name. Поэтому я решил попробовать PowerShell Jobs, и хотя я думаю, что они будут действительно хороши для длинных фоновых заданий, если вы просто хотите быстро получить небольшую часть информации в фоновом режиме, время инициализации неудобно (например, 2-3 се c за задание), поэтому я решил использовать Start-Process для выгрузки значений во временные файлы, пока остальная часть моего сценария выполняется. Я думаю, что я делаю это правильно, но если вы запустите эту функцию 3 или 4 раза, вы заметите, что имя ЦП не заполнено. есть более быстрый способ параллельно запускать небольшие фоновые задания? Я знаю, что есть. 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)"
    ""
}

1 Ответ

1 голос
/ 17 февраля 2020

Для запуска заданий в фоновом режиме в powershell, есть 3 способа go об этом


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

Если вы действительно хотите запускать задания в фоновом режиме, когда каждое задание не зависит друг от друга, вам придется подумать об использовании первого или второго параметра, поскольку ни один из них не требует вывода для записи в файл.

Invoke-Command запускает новый сеанс с системой и запускает задание в новом экземпляре.

Start-Job создает новое задание в фоновом режиме под новым экземпляром powershell, занимает немного больше времени для выделения ресурсы и начать процесс. Как и start-process, Start-Job будет запускать задание в отдельном экземпляре powershell.exe.

Start-Process требует, чтобы вы перенаправили стандартный вывод в файл [ 1] . Вы должны полагаться на производительность диска и скорость чтения и записи. Вы также должны убедиться, что не более одного потока читает / записывает на выходе этого процесса.

Рекомендация Я нашел Invoke-Command как самый быстрый при запуске 100 одновременных заданий для получения информации о процессоре. Эта опция требует, чтобы вы указали -ComputerName, который затем требует, чтобы вы были администратором, чтобы запустить сеанс winrm с localhost. Если вы не выводите информацию о задании при создании заданий, это не отнимает значительного времени.

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: указывает файл. Этот командлет отправляет выходные данные, сгенерированные процессом, в указанный вами файл. Введите путь и имя файла. По умолчанию вывод отображается на консоли.

[2] Start-Job

Командлет Start-Job запускает фоновое задание PowerShell на локальном компьютере. ... Фоновое задание PowerShell запускает команду, не взаимодействуя с текущим сеансом.

[3] Invoke-Command

Командлет Invoke-Command выполняет команды на локальном или удаленном компьютере и возвращает все выходные данные команд, включая ошибки. ... Для запуска команды в фоновом задании используйте параметр AsJob

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...