Questão Matando o processo de violação de memória, mas mantendo os pais seguros em Powershell


Preciso de ajuda para matar o processo infantil, mas manter os pais seguros. Eu sou novo no script do powershell [obviamente]. Aqui está exatamente o que eu preciso:

Eu tenho processos que estão usando mais de 500 000K de memória e quero colocá-los para baixo pelo script que será executado diariamente. Mas ao mesmo tempo eu quero evitar matar o processo pai, que também pode cair na categoria "acima de 500.000". Eu quero usá-lo para outra coisa, mas como um exemplo que eu estou mostrando árvore iexplore.exe. iexplore

Dois dos processos filhos estão violando minha memória max. Eu sou capaz de matar aqueles por script, mas eu preciso colocar a opção fail safe no processo pai caso também vai acima do limite especificado e que eu não tenho certeza de como abordar.

Isso é o que eu tenho até agora. O primeiro passo é obter todos os processos de violação:

Get-WmiObject -ComputerName $[list of servers] Win32_Process -Filter "name = '[app name]'" | Select-Object __Server,Name,@{Name='WorkingSet';Expression={[math]::Round(($_.WS/1MB),2)}},@{Name='VirtualMemory';Expression={[math]::Round(($_.VM/1MB),2)}} | Where-Object {$_.WorkingSet -gt $[my threshold]}

O próximo passo seria detê-los.

Eu ficaria grato por quaisquer sugestões.

Jules


1


origem




Respostas:


Usando o WMI, você pode obter o ParentProcessID do processo

gwmi -Class win32_process -Filter 'name like "%iexplore%"' | 
    select Name, ProcessID, ParentProcessID

Em uma nota lateral: embora improvável no caso do iexplore, é totalmente possível que um processo pai seja interrompido e o id seja reutilizado por outro processo.


1



Obrigado, isso seria útil se listasse apenas um parentalprocessídeo, mas na maioria dos casos há pelo menos dois e até quatro no meu caso. Eu acho que preciso de algo que exclua processos que têm um processo filho de parar. - jules d


Esta é uma maneira de criar esse tipo de lista. Primeiro, armazene todos os PIDs para o nome do processo em questão em uma matriz. Em seguida, filtre a lista de processos para incluir apenas aqueles em que o PID principal também está nessa matriz. Isso funciona porque o pai dos filhos iexplore será outro iexplore que está na matriz PID, e o pai do PRIMEIRO proce iexplore provavelmente era o Explorer, cujo PID não está nessa matriz.

$pids = (gwmi -Class win32_process -Filter 'name like "%iexplore%"' | select processid).processid
"PIDs"
$pids
"All Children"
gwmi -Class win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids } | select -prop commandline,processid
"Children > Size"
gwmi -Class win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids -and $_.ws -gt 500MB } | select -prop commandline,processid
"Parent(s)"
gwmi -Class win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -notin $pids } | select -prop commandline,processid

Observe que você não pode fazer isso com um único pipeline que começa com Get-WmiObject -ComputerName $[list of servers]. Isso cria uma coleção única de processos em vários dispositivos. Não há relação de processo pai entre processos em diferentes dispositivos. Você precisará aninhar a enumeração do processo dentro de um loop que é executado em cada servidor.

foreach ($server in $listOfServers) {
    $pids = (gwmi -comp $server win32_process -Filter 'name like "%iexplore%"' | select processid).processid
    # Report only, no kill
    gwmi -comp $server win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids -and $_.ws -gt 500MB } | select -prop commandline,processid
    # Kill, uncomment to enable
    # gwmi -comp $server win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids -and $_.ws -gt 500MB } | foreach { $_.terminate() }
}

0