web-dev-qa-db-fra.com

Comment savoir quels processus utilisent l'espace de swap sous Linux?

Sous Linux, comment savoir quel processus utilise le plus l'espace de swap?

230
Shameem

Exécuter top puis appuyer sur OpEnter. Les processus doivent maintenant être triés en fonction de leur utilisation de swap.

Voici une mise à jour car ma réponse initiale ne fournit pas une réponse exacte au problème mentionné dans les commentaires. De la htop FAQ :

Il n'est pas possible d'obtenir la taille exacte de l'espace d'échange utilisé d'un processus. Top simule cette information en faisant SWAP = VIRT - RES, mais ce n'est pas une bonne mesure, car d'autres éléments tels que la mémoire vidéo sont également pris en compte sur VIRT (par exemple: top indique que mon processus X utilise 81 Mo de swap, mais également indique que mon système dans son ensemble utilise seulement 2 Mo d’échange. Par conséquent, je n’ajouterai pas de colonne d’échange 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, à cause des pages partagées).

102
David Holm

Le meilleur scénario que j'ai trouvé se trouve sur cette page: http://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"
286
lolotux

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}/";
53
j3nda

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 qui a provoqué le remplacement de la plupart des pages.

Pour le premier, vous pouvez exécuter top et ordre par swap (appuyez sur 'Op'), pour le dernier, vous pouvez exécuter vmstat et rechercher des entrées non nulles pour 'so'.

10
Ronny Vindenes

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: use smem.

Voici un lien qui vous dit à la fois comment l'installer et comment l'utiliser:

http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/

10
Tom

Une autre variante de script évitant la boucle dans 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 est script.sh pour obtenir l'utilisation par programme avec un ordre aléatoire (jusqu'à comment awk stocke ses hachages) ou script.sh 1 pour trier la sortie par pid.

J'espère avoir suffisamment commenté le code pour dire ce qu'il fait.

6
Tensibai

La commande top contient également un champ permettant d'afficher le nombre de défauts de page d'un processus. Le processus avec un 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 encourent un grand nombre de défauts de page au début et que le nombre n’augmente pas ultérieurement. Nous devons donc vérifier si les défauts de page augmentent.

6
Amol Kulkarni

Encore deux variantes:

A Shell variante! (Pas bash seulement)

C'est exactement la même chose que script lolotux , mais sans aucun fork pour grep, awk ou ps. C'est beaucoup plus rapide!

Et comme bash est l’un des plus pauvres Shell en ce qui concerne les performances, un peu de travail a été fait pour s’assurer que ce script fonctionnera bien sous tiret , - busybox et un autre. 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 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 Shell avant!

Et une version Perl

Devenu un script pas si simple , il est temps 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 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
5
F. Hauri

J'ai adapté un script différent sur le Web à cette longue ligne:

 { 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 ; }

Ce 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 entrées Swap: 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; }

Le résultat de cette version est en deux colonnes: pid, montant de l'échange. Dans la version ci-dessus, la tr supprime les composants non numériques. Dans les deux cas, la sortie est triée numériquement par pid.

4
Otheus

Sur MacOSX, vous exécutez aussi top commande mais vous devez taper "o" puis "vsize" puis ENTER.

3
Alexis

Je suppose que vous pourriez avoir une bonne idée en exécutant top et en recherchant des processus actifs utilisant beaucoup de mémoire. Effectuer cette opération par programme est plus difficile - il suffit de regarder les débats sans fin sur l'heuristique tueur Linux de MOO.

La permutation est une fonction de plus de mémoire utilisée active que celle installée, il est donc généralement difficile de la rejeter sur un seul processus. Si le problème persiste, la meilleure solution consiste à installer davantage de mémoire ou à apporter d'autres modifications systémiques.

2
dmckee

Donne les totaux et les pourcentages pour le processus utilisant swap

smem -t -p

enter image description here

Source: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/

1
Soumya Boral

iotop est un outil très utile. Il fournit des statistiques en direct sur l'utilisation des E/S et des échanges par processus/thread. Par défaut, il affiche par thread, mais vous pouvez utiliser iotop -P pour obtenir les informations par processus. Ce n'est pas disponible par défaut. Vous devrez peut-être installer via rpm/apt.

1
sunil

Je ne connais pas de réponse directe quant à la manière de trouver le processus utilisant exactement l'espace d'échange. Ce lien peut toutefois être tile . Un autre bon est par ici

Utilisez également un bon outil tel que htop pour voir quels processus utilisent beaucoup de mémoire et quelle quantité de swap est utilisée dans l’ensemble.

1
Jean Azzopardi

Voici une version qui sort 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 comptait pour moi 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
0
Dmitry z