Linux에서 스왑 공간을 더 많이 사용하는 프로세스를 어떻게 알 수 있습니까?
Linux에서 스왑 공간을 더 많이 사용하는 프로세스를 어떻게 알 수 있습니까?
답변:
top 을 실행 한 다음을 누릅니다 OpEnter. 이제 프로세스는 스왑 사용량별로 정렬되어야합니다.
주석에서 지적한대로 원래 답변이 문제에 대한 정확한 답변을 제공하지 않으므로 업데이트 내용입니다. 로부터 htop 자주 묻는 질문 :
프로세스에서 사용 된 스왑 공간의 정확한 크기를 얻을 수 없습니다. Top은 SWAP = VIRT-RES를 만들어서이 정보를 위조하지만, 비디오 메모리와 같은 다른 것들도 VIRT에 포함되기 때문에 좋은 척도는 아닙니다 (예 : top은 내 X 프로세스가 81M의 스왑을 사용하고 있지만 시스템 전체가 2M의 스왑 만 사용하고 있다고보고하므로이 정보를 얻는 신뢰할 수있는 방법을 모르기 때문에 비슷한 스왑 열을 htop에 추가하지 않습니다 (실제로는 얻을 수 없다고 생각합니다) 공유 페이지로 인해 정확한 숫자).
내가 찾은 최고의 스크립트는이 페이지에 있습니다 : http://northernmost.org/blog/find-out-what-is-using-your-swap/
다음은 스크립트의 한 가지 변형이며 루트가 필요하지 않습니다.
#!/bin/bash
# Get current swap usage for all running processes
# Erik Ljungstrom 27/05/2011
# Modified by Mikko Rantalainen 2012-08-09
# Pipe the output to "sort -nk3" to get sorted output
# Modified by Marc Methot 2014-09-18
# removed the need for sudo
SUM=0
OVERALL=0
for DIR in `find /proc/ -maxdepth 1 -type d -regex "^/proc/[0-9]+"`
do
PID=`echo $DIR | cut -d / -f 3`
PROGNAME=`ps -p $PID -o comm --no-headers`
for SWAP in `grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'`
do
let SUM=$SUM+$SWAP
done
if (( $SUM > 0 )); then
echo "PID=$PID swapped $SUM KB ($PROGNAME)"
fi
let OVERALL=$OVERALL+$SUM
SUM=0
done
echo "Overall swap used: $OVERALL KB"
Overall swap used: 260672 KB
무료 쇼 동안 738932
사용 ...
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
Debian / RH 6x +, Arch, Ubuntu (RH 5x has VmSize
) ( source ). @dgunchev와 마찬가지로 전체 스왑보다 훨씬 적습니다 free
. @ Tensibai는 아치에서 작동하지 않습니다. 당신의 awk는 무언가가 부족할 수 있습니다.
top
: northernmost.org/blog/swap-usage-5-years-later
다음은 스크립트의 다른 변형이지만 더 읽기 쉬운 출력을 제공하기 위해 정확한 결과를 얻으려면 루트로 실행해야합니다.
#!/bin/bash
# find-out-what-is-using-your-swap.sh
# -- Get current swap usage for all running processes
# --
# -- rev.0.3, 2012-09-03, Jan Smid - alignment and intendation, sorting
# -- rev.0.2, 2012-08-09, Mikko Rantalainen - pipe the output to "sort -nk3" to get sorted output
# -- rev.0.1, 2011-05-27, Erik Ljungstrom - initial version
SCRIPT_NAME=`basename $0`;
SORT="kb"; # {pid|kB|name} as first parameter, [default: kb]
[ "$1" != "" ] && { SORT="$1"; }
[ ! -x `which mktemp` ] && { echo "ERROR: mktemp is not available!"; exit; }
MKTEMP=`which mktemp`;
TMP=`${MKTEMP} -d`;
[ ! -d "${TMP}" ] && { echo "ERROR: unable to create temp dir!"; exit; }
>${TMP}/${SCRIPT_NAME}.pid;
>${TMP}/${SCRIPT_NAME}.kb;
>${TMP}/${SCRIPT_NAME}.name;
SUM=0;
OVERALL=0;
echo "${OVERALL}" > ${TMP}/${SCRIPT_NAME}.overal;
for DIR in `find /proc/ -maxdepth 1 -type d -regex "^/proc/[0-9]+"`;
do
PID=`echo $DIR | cut -d / -f 3`
PROGNAME=`ps -p $PID -o comm --no-headers`
for SWAP in `grep Swap $DIR/smaps 2>/dev/null| awk '{ print $2 }'`
do
let SUM=$SUM+$SWAP
done
if (( $SUM > 0 ));
then
echo -n ".";
echo -e "${PID}\t${SUM}\t${PROGNAME}" >> ${TMP}/${SCRIPT_NAME}.pid;
echo -e "${SUM}\t${PID}\t${PROGNAME}" >> ${TMP}/${SCRIPT_NAME}.kb;
echo -e "${PROGNAME}\t${SUM}\t${PID}" >> ${TMP}/${SCRIPT_NAME}.name;
fi
let OVERALL=$OVERALL+$SUM
SUM=0
done
echo "${OVERALL}" > ${TMP}/${SCRIPT_NAME}.overal;
echo;
echo "Overall swap used: ${OVERALL} kB";
echo "========================================";
case "${SORT}" in
name )
echo -e "name\tkB\tpid";
echo "========================================";
cat ${TMP}/${SCRIPT_NAME}.name|sort -r;
;;
kb )
echo -e "kB\tpid\tname";
echo "========================================";
cat ${TMP}/${SCRIPT_NAME}.kb|sort -rh;
;;
pid | * )
echo -e "pid\tkB\tname";
echo "========================================";
cat ${TMP}/${SCRIPT_NAME}.pid|sort -rh;
;;
esac
rm -fR "${TMP}/";
args
대신 comm
에 ps
내가 이름은 같지만 서로 다른 인수 (파이썬 gunicorn 프로세스의 무리)와 프로세스를 많이 가지고 있기 때문에 명령. ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
간단하게 할 수awk ' /VmSwap/ { print $2 }'
나는이 스레드가 다소 오래되었다는 것을 알았지 만, 방금 그랬던 것처럼 당신이 그것을 우연히 발견하면 또 다른 대답은 smem을 사용하는 것입니다.
다음은 설치 방법과 사용 방법을 알려주는 링크입니다.
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
쉘에서 루프를 피하는 또 다른 스크립트 변형 :
#!/bin/bash
grep VmSwap /proc/[0-9]*/status | awk -F':' -v sort="$1" '
{
split($1,pid,"/") # Split first field on /
split($3,swp," ") # Split third field on space
cmdlinefile = "/proc/"pid[3]"/cmdline" # Build the cmdline filepath
getline pname[pid[3]] < cmdlinefile # Get the command line from pid
swap[pid[3]] = sprintf("%6i %s",swp[1],swp[2]) # Store the swap used (with unit to avoid rebuilding at print)
sum+=swp[1] # Sum the swap
}
END {
OFS="\t" # Change the output separator to tabulation
print "Pid","Swap used","Command line" # Print header
if(sort) {
getline max_pid < "/proc/sys/kernel/pid_max"
for(p=1;p<=max_pid;p++) {
if(p in pname) print p,swap[p],pname[p] # print the values
}
} else {
for(p in pname) { # Loop over all pids found
print p,swap[p],pname[p] # print the values
}
}
print "Total swap used:",sum # print the sum
}'
표준 사용법은 script.sh
임의의 순서로 ( awk
해시를 저장 하는 방법에 따라) 프로그램 당 사용량을 얻 거나 script.sh 1
pid로 출력을 정렬하는 것입니다.
내가하는 일을 알 수있을만큼 코드에 주석을 달았기를 바랍니다.
bash
정렬 방법 (어휘, 숫자되지 않음)에 디렉토리를 확장합니다. 무작위 순서는 awk
배열을 저장 하는 방법 (해시 테이블)과 for p in pname
검색 방법에 달려 있습니다.
/proc/1/status
후에 /proc/1992/status
그리고 /
아스키 코드 위에 아스키 코드가 있습니다. 이것은 "랜덤 순서"모양과 느낌을줍니다. 나는 awk 해시 테이블에 동의합니다 , 나는 여기에 지름길을
/proc/1/status
/proc/1992/status
순서가 바이트 값을 기반으로하는 C 로케일에서 나오지 않습니다 . 데이터 정렬 알고리즘의 첫 번째 인스턴스에서 무시되고 이후 정렬 en_GB.UTF-8
되기 때문에 로케일 (또는 GNU 시스템의 경우)에서 수행 됩니다. 와 비교하십시오 . 이외의 로케일 에서 정렬 순서는 일반적으로 바이트 값을 기반 으로 하지 않습니다 . /
s
9
printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
C
소규모 시스템에는 설치 top
하거나 htop
설치할 수 없기 때문에 탐색 /proc
은 항상 가능합니다.
작은 시스템에서도 당신은 shell
...
이것은 lolotux 스크립트 와 정확히 동일 하지만 grep
, awk
또는에 대한 포크가 없습니다 ps
. 이것은 훨씬 빠릅니다!
그리고 세게 때리다 가장 가난한 사람 중 하나입니다 껍질 성능과 관련하여이 스크립트가 제대로 실행되도록하기 위해 약간의 작업이 수행되었습니다. 대시, 비지 박스그리고 다른 것. 그런 다음 ( Stéphane Chazelas 덕분에 ) 다시 훨씬 더 빨리됩니다!
#!/bin/sh
# Get current swap usage for all running processes
# Felix Hauri 2016-08-05
# Rewritted without fork. Inspired by first stuff from
# Erik Ljungstrom 27/05/2011
# Modified by Mikko Rantalainen 2012-08-09
# Pipe the output to "sort -nk3" to get sorted output
# Modified by Marc Methot 2014-09-18
# removed the need for sudo
OVERALL=0
rifs=`printf ': \t'`
for FILE in /proc/[0-9]*/status ;do
SUM=0
while IFS="$rifs" read FIELD VALUE ;do
case $FIELD in
Pid ) PID=$VALUE ;;
Name ) PROGNAME="$VALUE" ;;
VmSwap ) SUM=$((SUM=${VALUE% *})) ;;
esac
done <$FILE
[ $SUM -gt 0 ] &&
printf "PID: %9d swapped: %11d KB (%s)\n" $PID $SUM "$PROGNAME"
OVERALL=$((OVERALL+SUM))
done
printf "Total swapped memory: %14u KB\n" $OVERALL
큰 따옴표를 잊어 버리지 마십시오 "$PROGNAME"
! Stéphane Chazelas의 의견 참조 :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
echo $PROGNAME
현명한 시스템에서 큰 따옴표없이 시도 하지 말고 현재 쉘을 죽일 준비를하십시오!
이것이 간단한 스크립트 가 아니기 때문에 보다 효율적인 언어를 사용하여 전용 도구를 작성해야합니다.
#!/usr/bin/perl -w
use strict;
use Getopt::Std;
my ($tot,$mtot)=(0,0);
my %procs;
my %opts;
getopt('', \%opts);
sub sortres {
return $a <=> $b if $opts{'p'};
return $procs{$a}->{'cmd'} cmp $procs{$b}->{'cmd'} if $opts{'c'};
return $procs{$a}->{'mswap'} <=> $procs{$b}->{'mswap'} if $opts{'m'};
return $procs{$a}->{'swap'} <=> $procs{$b}->{'swap'};
};
opendir my $dh,"/proc";
for my $pid (grep {/^\d+$/} readdir $dh) {
if (open my $fh,"</proc/$pid/status") {
my ($sum,$nam)=(0,"");
while (<$fh>) {
$sum+=$1 if /^VmSwap:\s+(\d+)\s/;
$nam=$1 if /^Name:\s+(\S+)/;
}
if ($sum) {
$tot+=$sum;
$procs{$pid}->{'swap'}=$sum;
$procs{$pid}->{'cmd'}=$nam;
close $fh;
if (open my $fh,"</proc/$pid/smaps") {
$sum=0;
while (<$fh>) {
$sum+=$1 if /^Swap:\s+(\d+)\s/;
};
};
$mtot+=$sum;
$procs{$pid}->{'mswap'}=$sum;
} else { close $fh; };
};
};
map {
printf "PID: %9d swapped: %11d (%11d) KB (%s)\n",
$_, $procs{$_}->{'swap'}, $procs{$_}->{'mswap'}, $procs{$_}->{'cmd'};
} sort sortres keys %procs;
printf "Total swapped memory: %14u (%11u) KB\n", $tot,$mtot;
중 하나와 함께 실행할 수
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
,, 백 슬래시, 와일드 카드 또는 제어 문자가 포함되지 않은 것으로 가정합니다 .
[1-9]
이전 *
에 추가했습니다 (아니 self
, 아니 thread-self
)
Name
항목 /proc/*/status
은 해당 바이트 값 중 일부를 인코딩합니다. 예를 들어보십시오 perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. 너무 짧기 때문에 perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
변수를 인용하는 것을 잊었을 때 와 같은 것들로 수행 할 수있는 피해 는 제한적입니다.
웹의 다른 스크립트를이 긴 한 줄짜리에 적용했습니다.
{ date;for f in /proc/[0-9]*/status; do
awk '{k[$1]=$2} END { if (k["VmSwap:"]) print k["Pid:"],k["Name:"],k["VmSwap:"];}' $f 2>/dev/null;
done | sort -n ; }
그런 다음 cronjob에 던져서 출력을 로그 파일로 리디렉션합니다. 여기에있는 정보 Swap:
는 smaps 파일 의 항목 을 누적하는 것과 동일 하지만 확실하게하려면 다음을 사용할 수 있습니다.
{ date;for m in /proc/*/smaps;do
awk '/^Swap/ {s+=$2} END { if (s) print FILENAME,s }' $m 2>/dev/null;
done | tr -dc ' [0-9]\n' |sort -k 1n; }
이 버전의 출력은 pid, swap amount의 두 열에 있습니다. 위 버전에서 tr
숫자가 아닌 구성 요소를 제거합니다. 두 경우 모두 출력은 pid로 숫자로 정렬됩니다.
top
많은 메모리를 사용하여 활성 프로세스를 실행 하고 찾아서 추측 할 수 있다고 생각합니다 . 프로그래밍 방식으로이 작업을 수행하는 것이 더 어렵습니다. Linux OOM 킬러 휴리스틱에 대한 끝없는 토론을 살펴보십시오.
스와핑 더 갖는 메모리의 함수 인 활성 은 단일 프로세스에 비난 일반적 어렵도록 설치된다보다 사용. 지속적인 문제인 경우 가장 좋은 해결책은 더 많은 메모리를 설치하거나 다른 시스템 변경을 수행하는 것입니다.
스왑을 사용하여 프로세스에 대한 총계 및 백분율 제공
smem -t -p
출처 : https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
다음은 @loolotux의 스크립트와 동일하지만 출력 속도가 훨씬 빠르지 만 읽을 수있는 버전입니다. 그 루프는 내 컴퓨터에서 약 10 초가 걸리고 내 버전은 0.019 초가 걸리며 cgi 페이지로 만들고 싶었 기 때문에 나에게 중요합니다.
join -t / -1 3 -2 3 \
<(grep VmSwap /proc/*/status |egrep -v '/proc/self|thread-self' | sort -k3,3 --field-separator=/ ) \
<(grep -H '' --binary-files=text /proc/*/cmdline |tr '\0' ' '|cut -c 1-200|egrep -v '/proc/self|/thread-self'|sort -k3,3 --field-separator=/ ) \
| cut -d/ -f1,4,7- \
| sed 's/status//; s/cmdline//' \
| sort -h -k3,3 --field-separator=:\
| tee >(awk -F: '{s+=$3} END {printf "\nTotal Swap Usage = %.0f kB\n",s}') /dev/null
SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ) 을 추가하는 2015 년 커널 패치 이후로 비례 스왑 수를 얻을 수 있습니다. 즉, 프로세스가 많이 스왑 된 후 포크 된 프로세스를 의미합니다. 각각 50 %를 교환 한 것으로보고됩니다. 그리고 포크 중 하나 인 경우, 각 프로세스는 스왑 된 페이지의 33 %로 계산되므로 모든 스왑 사용량을 함께 계산하면 값에 프로세스 수를 곱한 값 대신 실제 스왑 사용량이 발생합니다.
한마디로 :
(cd /proc; for pid in [0-9]*; do printf "%5s %6s %s\n" "$pid" "$(awk 'BEGIN{sum=0} /SwapPss:/{sum+=$2} END{print sum}' $pid/smaps)" "$(cat $pid/comm)"; done | sort -k2n,2 -k1n,1)
첫 번째 열은 pid이고 두 번째 열은 KiB에서 스왑 사용량이며 나머지 행은 명령이 실행되고 있습니다. 동일한 스왑 수는 pid로 정렬됩니다.
위와 같은 라인을 방출 할 수 있습니다
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
이는 단순히 pid 15407을 가진 프로세스가 /proc/
프로세스 smaps
파일 목록을 보고 읽는 사이에 끝났음을 의미 합니다. 그것이 당신에게 중요하다면, 단순히 2>/dev/null
끝에 추가 하십시오. 다른 가능한 진단 기능도 손실 될 수 있습니다.
실제 예제의 경우, 이는 하나의 서버에서 실행되는 각 아파치 하위에 대해 ~ 40MB 스왑 사용량을보고하는 다른 도구를 하위 당 실제로 사용 된 7-3630KB 사이의 실제 사용량으로 변경합니다.