PowerShell(가장 최적)

PowerShell(가장 최적)

PowerShell 함수를 통해 세션당 사용되는 메모리를 가져오고 싶습니다. 연결이 끊긴 세션에만 관심이 있습니다. 작업 관리자에서 sessionID당 사용된 메모리를 볼 수 있습니다.

여기에 이미지 설명을 입력하세요

다음 스크립트를 통해 PowerShell에서 MB 단위로 사용되는 mem을 얻으려고 했습니다.

# Get all user sessions
$sessions = qwinsta | Where-Object { $_ -match 'Disc' }
$procs = get-process # | where-object {$_.ProcessName -ne "Idle"}

foreach ($session in $sessions)
{
    $sessionId = ($session -split '\s+')[2]
    $usrprocs = $procs | where-object {$_.SessionId -eq $sessionId}
    $usrMem=0
    foreach($proc in $usrprocs)
    {
         $usrMem = $usrMem + [int64]($proc.WorkingSet64/(1024*1024))         
    }
    echo "$sessionId, $usrMem"
}

그러나 이것은 나에게 다음과 같은 결과를 제공합니다.

20, 481
21, 451
22, 670
23, 763
24, 949

작업 관리자에 나열된 사용된 메모리 근처에는 없습니다. 세션당 RAM을 어떻게 얻을 수 있나요?

업데이트 Vomit IT의 제안에 따라 이렇게 했지만 여전히 잘못된 값이 표시됩니다.

# Get all user sessions
$sessions = qwinsta | Where-Object { ($_ -match 'Disc') }

foreach ($session in $sessions)
{
    $sessionId = ($session -split '\s+')[2]
    $usrprocs = Get-Process | Where-Object { $_.SessionId -eq $sessionId }
    $usrMem=0
    foreach($proc in $usrprocs)
    {
         $usrMem = $usrMem + [int](Get-Counter -Counter "\Process($($proc.Name))\Working Set - Private").CounterSamples.CookedValue / 1KB      
    }
    echo "$sessionId, $usrMem"
}

결과

20, 808288
22, 830872
23, 806404
24, 806312
25, 802892

답변1

PowerShell(가장 최적)

Vomit에게 감사드립니다;) 제가 원하는 대로 작동하고 연결이 끊긴 세션당 RAM 사용량을 볼 수 있게 해주었습니다. 나는 매우 느린 경험을 했습니다 Get-Counter. 루프의 각 호출은 ~1초 정도 걸립니다. 그래서 저는 Get-CimInstance -ClassName Win32_PerfRawData_PerfProc_Process작업 세트를 비공개로 설정하기로 결정했습니다. – 린커트

OP에서 강조한 바와 같이 의 성능은 해당 클래스에서 속성 값을 검색할 때만 Get-Counter큼 최적이 아닙니다 . Get-CimInstance이 PowerShell 변형은 이러한 고려 사항을 통합하여 중요한 경우 향상된 성능을 제공합니다.

$session = quser | Where-Object { ($_ -match 'Disc') } 2>&1;
$sId = $session | ForEach-Object  { ($_ -split '\s+')[2]};
$processes = Get-Process | Where-Object { $_.SessionId -in $sId };

foreach ($process in $processes) {
    $workingSet = [int](Get-CimInstance -ClassName Win32_PerfRawData_PerfProc_Process -Filter "Name='$($process.Name)'").WorkingSetPrivate / 1KB;
    "$($process.Id), $($workingSet)";
};

알았어

위의 해결 방법은 WorkingSetPrivate클래스의 특정 속성 값에 액세스하는 데 문제가 있을 수 있습니다. 필요한 경우 보다 바람직한 출력을 위해 null 및 0 값을 무시하는 조건부 논리를 추가하는 것을 고려하십시오.

foreach ($process in $processes) {
    $instance = Get-CimInstance -ClassName Win32_PerfRawData_PerfProc_Process -Filter "Name='$($process.Name)'"
    if ($instance.WorkingSetPrivate -ne $null -and $instance.WorkingSetPrivate -gt 0) {
        $workingSet = [int]($instance.WorkingSetPrivate / 1KB)
        "$($process.Id), $($workingSet)"
    }
}

기타 솔루션

이에 따라 이 솔루션을 작업에 통합이 문제를 해결할 것입니다. 이 예는 간단한 버전이며 그림에 표시된 값과 정확하게 일치합니다.작업 관리자활성 개인 RAM을 선호합니다.

본질적으로 이것은 ...

  • 반환된 각 프로세스 및 속성 값을 반복하기 위해 Get-Process명령을 루프에 넣습니다 .ForEach-Object
  • 한 필드에 PSCustomObject를 저장하는 데 , 를 사용합니다 .PID
  • 를 사용하여 반환할 을 Get-Counter지정하고 Working Set - Private이를 an으로 캐스팅 [int]한 다음 1 KB다른 필드에서 으로 나눕니다.

결과는 작업 관리자에서 볼 수 있는 것과 일치하는 PID열과 해당 속성에 대한 탭 보기가 있는 열을 반환합니다.Memory (active private)Details

파워셸

$session = quser | Where-Object { ($_ -match 'Disc') } 2>&1;
$sId = $session | ForEach-Object  { ($_ -split '\s+')[2]};

Get-Process | Where-Object { $_.SessionId -in $sId } | ForEach-Object {
    [PSCustomObject]@{
        "PID" = $_.Id
        "Memory (active private)" = [int](Get-Counter -Counter "\Process($($_.Name))\Working Set - Private").CounterSamples.CookedValue / 1KB
    };
};

산출

  PID Memory (active private)
  --- -----------------------
16464                     164
25920                     164
11412                     264
12284                     712
18488                     712
20084                     712
 3660                   96952
10416                   96952
18424                   96952
 1408                   59000

PowerShell(또 다른 변형)

다음은 PowerShell을 사용하는 또 다른 변형입니다.ForEach 루프 문이것이 중요한 경우 기존 논리와 더 유사하게 구분된 원하는 쉼표로 값만 출력합니다.

$session = quser | Where-Object { ($_ -match 'Disc') } 2>&1;
$sId = $session | ForEach-Object  { ($_ -split '\s+')[2]};

$processes = Get-Process | Where-Object { $_.SessionId -in $sId };

foreach ($process in $processes) {
    $workingSet = (Get-Counter -Counter "\Process($($process.Name))\Working Set - Private").CounterSamples.CookedValue / 1KB;
    "$($process.Id), $([int]$workingSet)";
};

산출

16464, 164
25920, 164
11412, 264
12284, 728
18488, 728
20084, 728
3660, 97732
10416, 97732
18424, 97732
1408, 57576

지원 리소스

관련 정보