Wie finde ich unter Linux heraus, welcher Prozess den Swap Space mehr nutzt?
Wie finde ich unter Linux heraus, welcher Prozess den Swap Space mehr nutzt?
Antworten:
Oben laufen lassen und dann drücken OpEnter. Jetzt sollten Prozesse nach ihrer Swap-Verwendung sortiert werden.
Hier ist ein Update, da meine ursprüngliche Antwort keine genaue Antwort auf das Problem liefert, wie in den Kommentaren angegeben. Aus den htop FAQ :
Es ist nicht möglich, die genaue Größe des verwendeten Auslagerungsraums eines Prozesses zu ermitteln. Top fälscht diese Informationen, indem er SWAP = VIRT - RES macht, aber das ist keine gute Metrik, da andere Dinge wie der Videospeicher auch auf VIRT zählen (zum Beispiel: top sagt, mein X-Prozess verwendet 81 Millionen Swap, aber es auch meldet, dass mein System als Ganzes nur 2 Millionen Swap verwendet. Daher werde ich htop keine ähnliche Swap-Spalte hinzufügen, da ich keinen zuverlässigen Weg kenne, um diese Informationen zu erhalten (eigentlich glaube ich nicht, dass es möglich ist, sie zu erhalten eine genaue Anzahl, wegen freigegebener Seiten).
Das beste Skript, das ich gefunden habe, befindet sich auf dieser Seite: http://northernmost.org/blog/find-out-what-is-using-your-swap/
Hier ist eine Variante des Skripts und kein Root erforderlich:
#!/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
, während kostenlose Shows 738932
wie verwendet ...
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
für Debian / RH 6x +, Arch, Ubuntu (RH 5x hat VmSize
) ( Quelle ). Wie bei @dgunchev gibt es viel weniger Total Swap als free
. @Tensibai funktioniert nicht bei Arch; Ihrem awk kann etwas fehlen.
top
: northmost.org/blog/swap-usage-5-years-later
Hier ist eine andere Variante des Skripts, die jedoch eine besser lesbare Ausgabe ermöglichen soll (Sie müssen diese als Root ausführen, um genaue Ergebnisse zu erhalten):
#!/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
statt comm
in dem ps
Befehl , da ich viele Prozesse mit dem gleichen Namen , aber unterschiedlichen Argumenten (eine Reihe von Python gunicorn Prozessen) habe. ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
könnte vereinfacht werden alsawk ' /VmSwap/ { print $2 }'
Ich habe bemerkt, dass dieser Thread ziemlich alt ist, aber wenn Sie zufällig darauf stoßen, wie ich es gerade getan habe, lautet eine andere Antwort: Verwenden Sie smem.
Hier ist ein Link, der Ihnen erklärt, wie Sie es installieren und wie Sie es verwenden:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Es ist nicht ganz klar, ob Sie den Prozess finden möchten, bei dem die meisten Seiten ausgetauscht wurden, oder den Prozess, bei dem die meisten Seiten ausgetauscht wurden.
Zum ersten können Sie top
per Swap ausführen und bestellen (drücken Sie 'Op'), zum letzteren können Sie vmstat
Einträge ungleich Null für 'so' ausführen und suchen.
Der Befehl top enthält auch ein Feld, in dem die Anzahl der Seitenfehler für einen Prozess angezeigt wird. Der Prozess mit den maximalen Seitenfehlern ist der Prozess, der am meisten ausgetauscht wird. Bei lang laufenden Daemons kann es sein, dass sie zu Beginn eine große Anzahl von Seitenfehlern aufweisen und die Anzahl später nicht zunimmt. Wir müssen also beobachten, ob die Seitenfehler zunehmen.
Eine andere Skriptvariante, die die Schleife in der Shell vermeidet:
#!/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
}'
Die Standardverwendung besteht script.sh
darin, die Verwendung pro Programm in zufälliger Reihenfolge abzurufen (bis hin zur awk
Speicherung der Hashes) oder script.sh 1
die Ausgabe nach PID zu sortieren.
Ich hoffe, ich habe den Code genug kommentiert, um zu sagen, was er tut.
bash
die Verzeichnisse sortiert erweitert werden (lexikalisch, nicht numerisch). Die zufällige Reihenfolge hängt davon ab, wie awk
die Arrays gespeichert werden (Hash-Tabelle) und wie sie for p in pname
abgerufen werden.
/proc/1/status
kommt /proc/1992/status
und dass der /
ASCII-Code über dem 9-ASCII-Code liegt. Dies ergibt auch ein "zufälliges" Look & Feel. Ich stimme der awk-Hash-Tabelle zu Ich habe hier eine Verknüpfung genommen. Sie können die Antwort jederzeit bearbeiten, um die Zuordnung im Bearbeitungsverlauf
/proc/1/status
würde nicht /proc/1992/status
im Gebietsschema C kommen, in dem die Reihenfolge auf dem Bytewert basiert. Dies geschieht in Ihrem Gebietsschema (oder in meinem en_GB.UTF-8
auf einem GNU-System), da /
es in erster Linie im Kollatierungsalgorithmus ignoriert wird (und danach s
sortiert 9
). Vergleiche printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
mit printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
. In anderen Gebietsschemas als basiert C
die Sortierreihenfolge im Allgemeinen nicht auf dem Bytewert.
Da das Surfen auf kleinen Systemen nicht möglich ist top
oder htop
nicht /proc
möglich ist, bleibt das Surfen immer möglich.
Selbst auf kleinen Systemen finden Sie eine shell
...
Das ist genau das gleiche als lolotux Skript , aber ohne Gabel grep
, awk
oder ps
. Das geht viel schneller!
Und wie Bash ist einer der ärmsten Schale In Bezug auf die Leistung wurde ein wenig Arbeit geleistet, um sicherzustellen, dass dieses Skript gut funktioniert Strich, Busyboxund einige andere. Dann ( dank Stéphane Chazelas ) wieder viel schneller!
#!/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
Vergessen Sie nicht, doppelt zu zitieren "$PROGNAME"
! Siehe Stéphane Chazelas 'Kommentar :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
Versuchen Sie es nicht echo $PROGNAME
ohne doppeltes Anführungszeichen auf einem vernünftigen System und seien Sie bereit, die aktuelle Shell vorher zu töten!
Da dies ein nicht so einfaches Skript wird, wird es Zeit, ein spezielles Tool mit einer effizienteren Sprache zu schreiben.
#!/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;
könnte mit einem von laufen
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
, Backslash, Platzhalter oder Steuerzeichen enthalten.
[1-9]
zuvor hinzugefügt, *
um nur nummerierte Pfade zu zählen (nein self
, noch thread-self
)
Name
Eintrag in /proc/*/status
codiert einige dieser Bytewerte. Versuchen Sie es zum Beispiel perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Weil es so kurz ist, ist der Schaden, der mit Dingen wie angerichtet werden kann, perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
begrenzt, wenn Sie vergessen, Ihre Variablen anzugeben.
Ich habe ein anderes Skript im Web an diesen langen Einzeiler angepasst:
{ 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 ; }
Was ich dann in einen Cronjob werfe und die Ausgabe in eine Protokolldatei umleitung. Die Informationen hier sind die gleichen wie beim Sammeln der Swap:
Einträge in der Smaps-Datei. Wenn Sie jedoch sicher sein möchten, können Sie Folgendes verwenden:
{ 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; }
Die Ausgabe dieser Version erfolgt in zwei Spalten: pid, Swap-Betrag. In der obigen Version werden tr
die nicht numerischen Komponenten entfernt. In beiden Fällen wird die Ausgabe numerisch nach pid sortiert.
Ich nehme an, Sie könnten eine gute Vermutung anstellen, indem Sie top
aktive Prozesse mit viel Speicher ausführen und suchen. Dies programmatisch zu tun ist schwieriger - sehen Sie sich nur die endlosen Debatten über die Linux-OOM-Killer-Heuristik an.
Das Austauschen ist eine Funktion, bei der mehr Speicher aktiv genutzt wird als installiert ist. Daher ist es normalerweise schwierig, einen einzelnen Prozess dafür verantwortlich zu machen. Wenn es sich um ein anhaltendes Problem handelt, besteht die beste Lösung darin, mehr Speicher zu installieren oder andere systemische Änderungen vorzunehmen.
Gibt Summen und Prozentsätze für den Prozess mit Swap an
smem -t -p
Quelle: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Ich kenne keine direkte Antwort darauf, wie ich genau herausfinden kann, welcher Prozess den Swap Space verwendet. Dieser Link kann jedoch hilfreich sein . Ein weiterer guter ist hier
Verwenden Sie außerdem ein gutes Tool wie htop, um festzustellen, welche Prozesse viel Speicher belegen und wie viel Swap insgesamt verwendet wird.
iotop
ist ein sehr nützliches Werkzeug. Es gibt Live-Statistiken der E / A- und Swap-Nutzung pro Prozess / Thread. Standardmäßig wird pro Thread angezeigt, Sie können jedoch iotop -P
pro Prozess Informationen abrufen. Dies ist standardmäßig nicht verfügbar. Möglicherweise müssen Sie über rpm / apt installieren.
Hier ist eine Version, die das gleiche wie das Skript von @loolotux ausgibt, aber viel schneller ist (obwohl sie weniger lesbar ist). Diese Schleife dauert auf meinem Computer ungefähr 10 Sekunden, meine Version dauert 0,019 Sekunden, was mir wichtig war, weil ich daraus eine CGI-Seite machen wollte.
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
Seit dem Kernel-Patch des Jahres 2015, der hinzufügt SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ), kann man endlich eine proportionale Swap-Anzahl erhalten, was bedeutet, dass beide Prozesse gegabelt wurden, wenn ein Prozess viel getauscht und dann gegabelt wurde Es wird berichtet, dass jeweils 50% getauscht werden. Und wenn einer der beiden sich teilt, wird jeder Prozess mit 33% der ausgetauschten Seiten gezählt. Wenn Sie also alle diese Auslagerungsnutzungen zusammenzählen, erhalten Sie eine echte Auslagerungsnutzung anstelle des Werts multipliziert mit der Prozessanzahl.
Zusamenfassend:
(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)
Die erste Spalte ist pid, die zweite Spalte ist die Swap-Verwendung in KiB und der Rest der Zeile ist der Befehl, der ausgeführt wird. Identische Swap-Zählungen werden nach PID sortiert.
Oben können Zeilen wie
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
Dies bedeutet einfach, dass der Prozess mit pid 15407 zwischen dem Anzeigen in der Liste für /proc/
und dem Lesen der Prozessdatei beendet wurde smaps
. Wenn Ihnen das wichtig ist, fügen Sie es einfach 2>/dev/null
am Ende hinzu. Beachten Sie, dass Sie möglicherweise auch andere mögliche Diagnosen verlieren.
Im realen Beispielfall ändert dies andere Tools, die eine Swap-Nutzung von ~ 40 MB für jedes auf einem Server ausgeführte Apache-Kind melden, in eine tatsächliche Nutzung von 7 bis 3630 KB, die tatsächlich pro Kind verwendet wird.