W systemie Linux, w jaki sposób mogę dowiedzieć się, który proces bardziej wykorzystuje przestrzeń wymiany?
W systemie Linux, w jaki sposób mogę dowiedzieć się, który proces bardziej wykorzystuje przestrzeń wymiany?
Odpowiedzi:
Uruchom na górze, a następnie naciśnij OpEnter. Teraz procesy powinny być posortowane według użycia wymiany.
Oto aktualizacja, ponieważ moja pierwotna odpowiedź nie zawiera dokładnej odpowiedzi na problem, jak wskazano w komentarzach. Z htop FAQ :
Nie jest możliwe uzyskanie dokładnego rozmiaru używanej przestrzeni wymiany procesu. Top fałszuje te informacje, tworząc SWAP = VIRT - RES, ale nie jest to dobra miara, ponieważ inne rzeczy, takie jak pamięć wideo, również liczą się z VIRT (na przykład: top mówi, że mój proces X używa 81 mln swapów, ale także zgłasza, że mój system używa tylko 2 mln swapów. Dlatego nie dodam podobnej kolumny swap do htop, ponieważ nie znam niezawodnego sposobu na uzyskanie tych informacji (w rzeczywistości nie sądzę, że można uzyskać dokładna liczba z powodu udostępnionych stron).
Najlepszy skrypt, jaki znalazłem, znajduje się na tej stronie: http://northernmost.org/blog/find-out-what-is-using-your-swap/
Oto jeden wariant skryptu i nie wymaga rootowania:
#!/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
, podczas gdy darmowe pokazy 738932
używane ...
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
dla Debian / RH 6x +, Arch, Ubuntu (RH 5x has VmSize
) ( źródło ). Podobnie jak @gunchev daje znacznie mniej całkowitą zamianę niż free
. @Tensibai nie działa w Arch; twój awk może czegoś nie mieć.
top
: northernmost.org/blog/swap-usage-5-years-later
Oto inny wariant skryptu, ale przeznaczony do zapewnienia bardziej czytelnego wyniku (musisz uruchomić go jako root, aby uzyskać dokładne wyniki):
#!/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
zamiast comm
w ps
poleceniu, ponieważ mam wiele procesów o tej samej nazwie, ale z różnymi argumentami (kilka procesów gunicorn w Pythonie). To ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
można to uprościć jakoawk ' /VmSwap/ { print $2 }'
Zauważyłem, że ten wątek jest dość stary, ale jeśli trafisz na niego, tak jak właśnie to zrobiłem, inna odpowiedź brzmi: użyj smem.
Oto link, który mówi zarówno, jak zainstalować i jak go używać:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Nie jest do końca jasne, czy chcesz znaleźć proces, który spowodował zamianę większości stron, lub proces, który spowodował zamianę większości stron.
W przypadku pierwszego możesz uruchomić top
i zamówić przez zamianę (naciśnij „Op”), w drugim przypadku możesz uruchomić vmstat
i poszukać niezerowych wpisów dla „tak”.
Górne polecenie zawiera także pole do wyświetlenia liczby błędów strony dla procesu. Proces z maksymalną liczbą błędów stron byłby procesem, który najbardziej zamienia. W przypadku długo działających demonów może to oznaczać, że na początku powodują one dużą liczbę błędów stron, a liczba ta nie wzrasta później. Musimy więc obserwować, czy liczba błędów stron rośnie.
Kolejny wariant skryptu omijający pętlę w powłoce:
#!/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
}'
Standardowe użycie polega script.sh
na uzyskiwaniu użycia według programu z losową kolejnością (aż do sposobu awk
przechowywania jego skrótów) lub script.sh 1
sortowaniu wyników według pid.
Mam nadzieję, że skomentowałem kod na tyle, aby powiedzieć, co on robi.
bash
rozwija katalogi w sposób posortowany (leksykalny, nie numeryczny). Losowa kolejność zależy od tego, jak awk
przechowuje swoje tablice (tablica skrótów) i jak for p in pname
je pobiera.
/proc/1/status
następuje /proc/1992/status
i że /
ma kod ascii powyżej kodu ascii 9. To daje wygląd „losowy porządek” też. Zgadzam się z tabelą skrótów awk , Skorzystałem tutaj ze skrótu. Edytuj odpowiedź, aby zachować atrybucję w historii edycji
/proc/1/status
nie pojawiłby się /proc/1992/status
w lokalizacji C, gdzie kolejność oparta jest na wartości bajtów. Dzieje się to w twoich ustawieniach narodowych (lub w moim en_GB.UTF-8
w systemie GNU), ponieważ /
są one ignorowane w algorytmie sortowania (i s
sortuje po 9
). Porównaj printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
z printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
. W lokalizacjach innych niż C
porządek sortowania zasadniczo nie jest oparty na wartości bajtów.
Ponieważ top
lub htop
nie można go zainstalować w małych systemach, przeglądanie /proc
zawsze jest możliwe.
Nawet w małych systemach znajdziesz shell
...
To jest dokładnie to samo niż lolotux scenariusza , ale bez rozwidleniu grep
, awk
lub ps
. To jest o wiele szybsze!
I jako grzmotnąć jest jednym z najbiedniejszych muszla jeśli chodzi o wydajność, wykonano trochę pracy, aby skrypt działał dobrze dziarskość, busyboxi niektóre inne. Potem ( dzięki Stéphane Chazelas ) znów stać się znacznie szybszym!
#!/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
Nie zapomnij o podwójnej wycenie "$PROGNAME"
! Zobacz komentarz Stéphane Chazelas :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
Nie próbuj echo $PROGNAME
bez podwójnego cytowania na rozsądnym systemie i bądź gotowy zabić wcześniejszą powłokę!
Ponieważ staje się to nie tak prostym skryptem, nadchodzi czas na napisanie dedykowanego narzędzia przy użyciu bardziej wydajnego języka.
#!/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;
mógł biec z jednym z
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
, odwrotnego ukośnika, symboli wieloznacznych ani znaków kontrolnych.
[1-9]
wcześniej *
do zliczania tylko ponumerowanych ścieżek (nie self
, ani thread-self
)
Name
Wpis /proc/*/status
koduje niektóre z tych wartości bajtów. Spróbuj na przykład perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Ponieważ jest tak krótki, szkody, które można wyrządzić za pomocą takich rzeczy, perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
są ograniczone, gdy zapomnisz podać swoje zmienne.
Dostosowałem inny skrypt w sieci do tego długiego linku:
{ 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 ; }
Które następnie wrzucam do cronjob i przekierowuję dane wyjściowe do pliku dziennika. Informacje tutaj są takie same, jak gromadzenie Swap:
wpisów w pliku smaps, ale jeśli chcesz być pewien, możesz użyć:
{ 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; }
Dane wyjściowe tej wersji są w dwóch kolumnach: pid, kwota zamiany. W powyższej wersji tr
usuwa elementy nienumeryczne. W obu przypadkach dane wyjściowe są sortowane numerycznie według pid.
Przypuszczam, że można się domyślić, biegając top
i szukając aktywnych procesów przy użyciu dużej ilości pamięci. Wykonanie tego programowo jest trudniejsze - wystarczy spojrzeć na niekończące się debaty na temat heurystyki zabójcy Linux OOM.
Zamiana jest funkcją posiadania większej ilości pamięci w aktywnym użyciu niż jest zainstalowana, więc zwykle ciężko jest winić ją za pojedynczy proces. Jeśli jest to ciągły problem, najlepszym rozwiązaniem jest zainstalowanie większej ilości pamięci lub wprowadzenie innych zmian systemowych.
Podaje sumy i procenty dla procesu z wykorzystaniem swap
smem -t -p
Źródło: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Nie znam żadnej bezpośredniej odpowiedzi, jak znaleźć dokładnie proces wykorzystujący przestrzeń wymiany, jednak ten link może być pomocny . Kolejny dobry jest tutaj
Ponadto użyj dobrego narzędzia, takiego jak htop, aby zobaczyć, które procesy zużywają dużo pamięci i ile ogólnie używana jest zamiana.
iotop
jest bardzo przydatnym narzędziem. Daje bieżące statystyki wykorzystania I / O i zamiany na proces / wątek. Domyślnie pokazuje się na wątek, ale możesz zrobić, iotop -P
aby uzyskać informacje na temat procesu. To nie jest domyślnie dostępne. Może być konieczne zainstalowanie przez rpm / apt.
Oto wersja, która wypisuje to samo co skrypt @loolotux, ale jest znacznie szybsza (choć mniej czytelna). Ta pętla zajmuje około 10 sekund na mojej maszynie, moja wersja zajmuje 0,019 s, co miało dla mnie znaczenie, ponieważ chciałem zrobić z niej stronę 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
Od roku 2015 łatka na jądro, która dodaje SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ), można w końcu uzyskać proporcjonalną liczbę zamian, co oznacza, że jeśli proces dużo zamienił, a potem się rozwidla, oba rozwidlone zostanie zgłoszona zamiana po 50%. A jeśli oba rozwidlają się, każdy proces jest liczony w 33% zamienionych stron, więc jeśli policzysz wszystkie te zamiany razem, otrzymasz rzeczywiste użycie zamiany zamiast wartości pomnożonej przez liczbę procesów.
W skrócie:
(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)
Pierwsza kolumna to pid, druga kolumna to użycie zamiany w KiB, a reszta linii jest wykonywana. Identyczne liczby zamian są sortowane według pid.
Powyżej mogą emitować linie takie jak
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
co oznacza po prostu, że proces z pid 15407 zakończył się między wyświetleniem go na liście dla /proc/
a odczytaniem smaps
pliku procesu . Jeśli to dla Ciebie ważne, po prostu dodaj2>/dev/null
do końca. Pamiętaj, że potencjalnie utracisz także wszelkie inne możliwe elementy diagnostyczne.
W prawdziwym przypadku przykładowym zmienia to inne narzędzia zgłaszające użycie ~ 40 MB zamiany dla każdego elementu potomnego apache działającego na jednym serwerze na faktyczne użycie w zakresie 7-3630 KB faktycznie używanych na dziecko.