Sotto Linux, come faccio a sapere quale processo utilizza maggiormente lo spazio di swap?
Sotto Linux, come faccio a sapere quale processo utilizza maggiormente lo spazio di swap?
Risposte:
Eseguire la parte superiore quindi premere OpEnter. Ora i processi dovrebbero essere ordinati in base al loro utilizzo di swap.
Ecco un aggiornamento poiché la mia risposta originale non fornisce una risposta esatta al problema, come sottolineato nei commenti. Dalle domande frequenti su htop :
Non è possibile ottenere la dimensione esatta dello spazio di swap utilizzato di un processo. Top falsifica queste informazioni creando SWAP = VIRT - RES, ma questa non è una buona metrica, perché anche altre cose come la memoria video conta su VIRT (ad esempio: top dice che il mio processo X sta usando 81M di swap, ma anche segnala che il mio sistema nel suo complesso utilizza solo 2 milioni di swap. Pertanto, non aggiungerò una colonna Swap simile a htop perché non conosco un modo affidabile per ottenere queste informazioni (in realtà, non penso che sia possibile ottenere un numero esatto, a causa delle pagine condivise).
La migliore sceneggiatura che ho trovato è su questa pagina: http://northernmost.org/blog/find-out-what-is-using-your-swap/
Ecco una variante dello script e non è necessaria alcuna radice:
#!/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
, mentre spettacoli gratuiti 738932
come usato ...
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
per Debian / RH 6x +, Arch, Ubuntu (RH 5x ha VmSize
) ( sorgente ). Come @dgunchev, offre uno swap totale molto meno di free
. @Tensibai non funziona su Arch; il tuo awk potrebbe non avere qualcosa.
top
: northernmost.org/blog/swap-usage-5-years-later
Ecco un'altra variante dello script, ma intendeva fornire un output più leggibile (è necessario eseguirlo come root per ottenere risultati esatti):
#!/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
invece che comm
nel ps
comando poiché ho molti processi con lo stesso nome ma argomenti diversi (un gruppo di processi Python Gunicorn). ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
awk ' /VmSwap/ { print $2 }'
Ho notato che questo thread è piuttosto vecchio, ma se ti capita di imbatterti in esso, come ho appena fatto, un'altra risposta è: usa smem.
Ecco un link che ti dice sia come installarlo che come usarlo:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Non è del tutto chiaro se vuoi dire che vuoi trovare il processo che ha sostituito la maggior parte delle pagine o il processo che ha causato lo scambio della maggior parte delle pagine.
Per il primo è possibile eseguire top
e ordinare tramite swap (premere 'Op'), per il secondo è possibile eseguire vmstat
e cercare voci diverse da zero per 'so'.
Il comando superiore contiene anche un campo per visualizzare il numero di errori di pagina per un processo. Il processo con massimo errore di pagina sarebbe il processo che sta scambiando di più. Per i demoni a esecuzione prolungata potrebbe essere che all'inizio si verifichino un numero elevato di errori di pagina e il numero non aumenterà in seguito. Quindi dobbiamo osservare se gli errori di pagina stanno aumentando.
Un'altra variante di script che evita il loop nella shell:
#!/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
}'
L'utilizzo standard è script.sh
quello di ottenere l'utilizzo per programma con ordine casuale (fino a come awk
memorizza i suoi hash) o script.sh 1
ordinare l'output per pid.
Spero di aver commentato abbastanza il codice per dire cosa fa.
bash
espande le directory in modo ordinato (lessicale, non numerico). L'ordine casuale dipende da come awk
memorizza le sue matrici (tabella hash) e da come le for p in pname
recupera.
/proc/1/status
viene dopo /proc/1992/status
e che /
ha un codice ASCII sopra il codice ASCII 9. Questo dà anche un aspetto e un "ordine casuale". Sono d'accordo con la tabella hash awk , Ho preso una scorciatoia qui. Sentiti libero di modificare la risposta per mantenere l'attribuzione nella cronologia delle modifiche.
/proc/1/status
non verrebbe dopo /proc/1992/status
nella locale C dove l'ordine si basa sul valore byte. Lo fa nel tuo locale (o nel mio en_GB.UTF-8
su un sistema GNU), perché /
viene ignorato nella prima istanza dell'algoritmo di fascicolazione (e s
ordina dopo 9
). Confronta printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
con printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
. In locali diversi da C
, l'ordinamento generalmente non si basa sul valore byte.
Poiché top
o htop
potrebbe non essere installato su piccoli sistemi, la navigazione /proc
rimane sempre possibile.
Anche su piccoli sistemi, troverai un shell
...
Questo è esattamente lo stesso dello script lolotux , ma senza fork a grep
, awk
o ps
. Questo è molto più veloce!
E come bash è uno dei più poveri conchiglia per quanto riguarda le prestazioni, è stato fatto un piccolo lavoro per garantire che questo script funzionasse bene trattino, busyboxe alcuni altri. Quindi, ( grazie a Stéphane Chazelas ,) diventa di nuovo molto più veloce!
#!/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
Non dimenticare di raddoppiare la citazione "$PROGNAME"
! Vedi il commento di Stéphane Chazelas :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
Non provare echo $PROGNAME
senza una doppia citazione sul sistema sensibile ed essere pronto a uccidere la shell corrente prima!
Dato che questo diventa uno script non così semplice , sta arrivando il momento di scrivere uno strumento dedicato usando un linguaggio più efficiente.
#!/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;
potrebbe essere eseguito con uno dei
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
, barra rovesciata, caratteri jolly o caratteri di controllo.
[1-9]
prima *
per contare solo i percorsi numerati (no self
, né thread-self
)
Name
voce in /proc/*/status
codifica alcuni di questi valori di byte. Prova ad esempio perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Perché è così breve, il danno che può essere fatto con cose del genere perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
è limitato quando ti dimentichi di citare le tue variabili.
Ho adattato una diversa sceneggiatura sul web a questo lungo one-liner:
{ 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 ; }
Che poi lancio in un cronjob e reindirizzo l'output a un file di registro. Le informazioni qui sono le stesse dell'accumulo delle Swap:
voci nel file smaps, ma se vuoi essere sicuro, puoi usare:
{ 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; }
L'output di questa versione è in due colonne: pid, importo di scambio. Nella versione precedente, tr
rimuove i componenti non numerici. In entrambi i casi, l'output viene ordinato numericamente per pid.
Suppongo che potresti avere una buona idea eseguendo top
e cercando processi attivi che usano molta memoria. Fare questo a livello di programmazione è più difficile --- basta guardare agli infiniti dibattiti sull'euristica killer di OOM Linux.
Scambio è una funzione di avere più memoria in attivo uso rispetto è installato, quindi è solitamente difficile colpa a un singolo processo. Se si tratta di un problema in corso, la soluzione migliore è installare più memoria o apportare altre modifiche sistemiche.
Fornisce i totali e le percentuali per il processo tramite swap
smem -t -p
Fonte: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Non conosco alcuna risposta diretta su come trovare esattamente quale processo sta utilizzando lo spazio di scambio, tuttavia, questo collegamento può essere utile . Un altro buono è qui
Inoltre, usa un buon strumento come htop per vedere quali processi stanno usando molta memoria e quanta swap in generale viene utilizzata.
iotop
è uno strumento molto utile. Fornisce statistiche in tempo reale di I / O e utilizzo degli swap per processo / thread. Per impostazione predefinita, mostra per thread ma è possibile fare iotop -P
per ottenere informazioni sul processo. Questo non è disponibile per impostazione predefinita. Potrebbe essere necessario installare tramite rpm / apt.
Ecco una versione che produce lo stesso script di @loolotux, ma è molto più veloce (anche se meno leggibile). Quel ciclo impiega circa 10 secondi sulla mia macchina, la mia versione impiega 0,019 s, il che conta per me perché volevo trasformarlo in una pagina 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
Dalla patch del kernel dell'anno 2015 che aggiunge SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ) si può finalmente ottenere un conteggio di swap proporzionale, il che significa che se un processo ha scambiato molto e poi si biforca, entrambi i processi biforcati sarà segnalato per scambiare il 50% ciascuno. E se uno dei due viene eseguito il fork, ogni processo viene conteggiato al 33% delle pagine scambiate, quindi se si contano tutti quegli utilizzi di scambio, si ottiene un reale utilizzo dello scambio anziché il valore moltiplicato per il conteggio dei processi.
In breve:
(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)
La prima colonna è pid, la seconda colonna è l'utilizzo dello scambio in KiB e il resto della riga è l'esecuzione del comando. I conteggi identici di swap sono ordinati per pid.
Sopra può emettere linee come
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
il che significa semplicemente che il processo con pid 15407 si è concluso tra vederlo nell'elenco /proc/
e leggere il smaps
file di processo . Se questo è importante per te, aggiungi semplicemente 2>/dev/null
fino alla fine. Tieni presente che potenzialmente perderai anche qualsiasi altra diagnostica possibile.
Nel caso di esempio nel mondo reale, questo cambia altri strumenti che riportano un utilizzo dello scambio di ~ 40 MB per ciascun figlio apache in esecuzione su un server in un utilizzo effettivo compreso tra 7-3630 KB realmente utilizzato per figlio.