Sous Linux, comment savoir quel processus utilise le plus l'espace de swap?
Sous Linux, comment savoir quel processus utilise le plus l'espace de swap?
Réponses:
Courez en haut puis appuyez sur OpEnter. Désormais, les processus doivent être triés selon leur utilisation de swap.
Voici une mise à jour car ma réponse d'origine ne fournit pas de réponse exacte au problème comme indiqué dans les commentaires. De la FAQ htop :
Il n'est pas possible d'obtenir la taille exacte de l'espace de swap utilisé d'un processus. Top simule ces informations en faisant SWAP = VIRT - RES, mais ce n'est pas une bonne métrique, car d'autres choses telles que la mémoire vidéo comptent également sur VIRT (par exemple: top dit que mon processus X utilise 81M de swap, mais il a également signale que mon système dans son ensemble n'utilise que 2 Mo de swap. Par conséquent, je n'ajouterai pas de colonne Swap similaire à htop car je ne connais pas de moyen fiable d'obtenir ces informations (en fait, je ne pense pas qu'il soit possible d'obtenir un nombre exact, en raison des pages partagées).
Le meilleur script que j'ai trouvé se trouve sur cette page: http : //n Northernmost.org/blog/find-out-what-is-using-your-swap/
Voici une variante du script et aucune racine nécessaire:
#!/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
, alors que les spectacles gratuits sont 738932
utilisés ...
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
pour Debian / RH 6x +, Arch, Ubuntu (RH 5x has VmSize
) ( source ). Comme @dgunchev, cela donne beaucoup moins de swap total que free
. @Tensibai ne fonctionne pas sur Arch; votre awk peut manquer de quelque chose.
top
: northernmost.org/blog/swap-usage-5-years-later
Voici une autre variante du script, mais destinée à donner une sortie plus lisible (vous devez l'exécuter en tant que root pour obtenir des résultats exacts):
#!/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
au lieu de comm
dans la ps
commande car j'ai beaucoup de processus avec le même nom mais des arguments différents (un tas de processus gunicorn en python). C'est à dire:ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
pourrait être simplifié commeawk ' /VmSwap/ { print $2 }'
J'ai remarqué que ce fil est plutôt ancien, mais si vous tombez dessus, comme je viens de le faire, une autre réponse est: utilisez smem.
Voici un lien qui vous indique à la fois comment l'installer et comment l'utiliser:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Ce n'est pas tout à fait clair si vous voulez dire que vous voulez trouver le processus qui a échangé la plupart des pages ou le processus qui a provoqué l'échange de la plupart des pages.
Pour le premier, vous pouvez exécuter top
et commander par swap (appuyez sur «Op»), pour ce dernier, vous pouvez exécuter vmstat
et rechercher des entrées non nulles pour «so».
La commande supérieure contient également un champ pour afficher le nombre de défauts de page pour un processus. Le processus avec le maximum de défauts de page serait le processus qui permute le plus. Pour les démons de longue durée, il se peut qu'ils entraînent un grand nombre de défauts de page au début et que le nombre n'augmente pas plus tard. Nous devons donc observer si les défauts de page augmentent.
Une autre variante de script évitant la boucle dans le 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'utilisation standard consiste script.sh
à obtenir l'utilisation par programme avec un ordre aléatoire (jusqu'à la façon dont awk
stocke ses hachages) ou script.sh 1
à trier la sortie par pid.
J'espère avoir suffisamment commenté le code pour dire ce qu'il fait.
bash
développe les répertoires de manière triée (lexicale et non numérique). L'ordre aléatoire dépend de la façon dont awk
stocke ses tableaux (table de hachage) et comment les for p in pname
récupère.
/proc/1/status
vient après /proc/1992/status
et qui /
a un code ascii au-dessus du code 9 ascii. Cela donne un aspect et une sensation "d'ordre aléatoire" aussi. Je suis d'accord avec la table de hachage awk , J'ai pris un raccourci ici. N'hésitez pas à modifier la réponse pour conserver l'attribution dans l'historique des modifications.
/proc/1/status
ne viendrait pas après /proc/1992/status
dans les paramètres régionaux C où l'ordre est basé sur la valeur d'octet. Il le fait dans votre environnement local (ou dans mon en_GB.UTF-8
sur un système GNU), car /
il est ignoré en première instance dans l'algorithme de classement (et s
trié après 9
). Comparez printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
avec printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
. Dans les paramètres régionaux autres que C
, l'ordre de tri n'est généralement pas basé sur la valeur d'octet.
Parce que top
ou htop
ne peut pas être installé sur de petits systèmes, la navigation /proc
reste toujours possible.
Même sur les petits systèmes, vous trouverez un shell
...
C'est exactement la même chose que le script lolotux , mais sans fork pour grep
, awk
ou ps
. C'est beaucoup plus rapide!
Et comme frapper est l'un des plus pauvres coquille en ce qui concerne les performances, un petit travail a été fait pour s'assurer que ce script fonctionnera bien sous tiret, occupéet quelques autres. Ensuite, ( grâce à Stéphane Chazelas ,) redevenez beaucoup plus rapide!
#!/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
N'oubliez pas de doubler la citation "$PROGNAME"
! Voir le commentaire de Stéphane Chazelas :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
N'essayez pas echo $PROGNAME
sans guillemet double sur le système sensible et soyez prêt à tuer le shell actuel avant!
Comme cela devient un script pas si simple , le temps est venu d'écrire un outil dédié en utilisant un langage plus efficace.
#!/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;
pourrait par courir avec l'un des
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
, de barre oblique inverse, de caractère générique ou de caractères de contrôle.
[1-9]
auparavant *
pour ne compter que les chemins numérotés (non self
, ni thread-self
)
Name
entrée dans /proc/*/status
code certaines de ces valeurs d'octets. Essayez par exemple perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Parce qu'il est si court, les dommages qui peuvent être causés avec des choses comme perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
sont limités lorsque vous oubliez de citer vos variables.
J'ai adapté un script différent sur le web à ce long 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 ; }
Que je jette ensuite dans un cronjob et redirige la sortie vers un fichier journal. Les informations ici sont les mêmes que l'accumulation des Swap:
entrées dans le fichier smaps, mais si vous voulez en être sûr, vous pouvez utiliser:
{ 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; }
La sortie de cette version est sur deux colonnes: pid, swap amount. Dans la version ci-dessus, les tr
bandes les composants non numériques. Dans les deux cas, la sortie est triée numériquement par pid.
Je suppose que vous pouvez obtenir une bonne estimation en exécutant top
et en recherchant des processus actifs utilisant beaucoup de mémoire. Faire cela par programme est plus difficile --- il suffit de regarder les débats sans fin sur l'heuristique du tueur Linux OOM.
Permutation est une fonction de mémoire possédant plus en actif usage que ce qui est installé, de sorte qu'il est généralement difficile de faute sur un seul processus. S'il s'agit d'un problème persistant, la meilleure solution consiste à installer plus de mémoire ou à effectuer d'autres modifications systémiques.
Donne des totaux et des pourcentages pour le processus utilisant le swap
smem -t -p
Source: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Je ne connais pas de réponse directe sur la façon de trouver exactement quel processus utilise l'espace d'échange, cependant, ce lien peut être utile . Un autre bon est ici
De plus, utilisez un bon outil comme htop pour voir quels processus utilisent beaucoup de mémoire et combien de swap global est utilisé.
iotop
est un outil très utile. Il donne des statistiques en direct des E / S et de l'utilisation des échanges par processus / thread. Par défaut, il affiche par thread, mais vous pouvez faire iotop -P
pour obtenir des informations par processus. Ce n'est pas disponible par défaut. Vous devrez peut-être installer via rpm / apt.
Voici une version qui produit le même que le script de @loolotux, mais est beaucoup plus rapide (bien que moins lisible). Cette boucle prend environ 10 secondes sur ma machine, ma version prend 0,019 s, ce qui m'importait parce que je voulais en faire une page 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
Depuis le correctif du noyau de l'année 2015 qui ajoute SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ), on peut enfin obtenir un nombre de swaps proportionnel, ce qui signifie que si un processus a beaucoup échangé puis se bifurque, les deux processus fourchus seront signalés comme échangeant 50% chacun. Et si l'un ou l'autre bifurque, chaque processus compte pour 33% des pages échangées, donc si vous comptez toutes ces utilisations de swap ensemble, vous obtenez une véritable utilisation de swap au lieu d'une valeur multipliée par le nombre de processus.
En bref:
(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 première colonne est pid, la deuxième colonne est l'utilisation de swap en KiB et le reste de la ligne est une commande en cours d'exécution. Les nombres de swaps identiques sont triés par pid.
Ci-dessus peut émettre des lignes telles que
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
ce qui signifie simplement que le processus avec le pid 15407 s'est terminé entre le voir dans la liste /proc/
et lire le smaps
fichier de processus . Si cela vous importe, ajoutez simplement 2>/dev/null
à la fin. Notez que vous risquez également de perdre tout autre diagnostic possible.
Dans le cas d'un exemple réel, cela modifie les autres outils signalant une utilisation de ~ 40 Mo de swap pour chaque enfant apache exécuté sur un serveur à une utilisation réelle comprise entre 7 et 3 630 Ko réellement utilisée par enfant.