memory tengo - ¿Cómo saber qué procesos están utilizando el espacio de intercambio en Linux?




mas consumen (13)

En Linux, ¿cómo puedo saber qué proceso está utilizando más el espacio de intercambio?


Answers

Aquí hay otra variante de la secuencia de comandos, pero destinada a proporcionar un resultado más legible (debe ejecutar esto como root para obtener resultados exactos):

#!/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}/";

iotop es una herramienta muy útil. Proporciona estadísticas en vivo de E / S y uso de intercambio por proceso / subproceso. Por defecto, se muestra por subproceso, pero puede hacer iotop -P para obtener información de proceso. Esto no está disponible por defecto. Puede que tenga que instalar a través de rpm / apt.



No está del todo claro si quiere decir que quiere encontrar el proceso de quién ha intercambiado la mayoría de las páginas o el proceso que causó que la mayoría de las páginas se intercambien.

Para el primero puede ejecutar top y ordenar por swap (presione 'Op'), para el último puede ejecutar vmstat y buscar entradas que no sean cero para 'so'.


El mejor script que he encontrado está en esta página: http://northernmost.org/blog/find-out-what-is-using-your-swap/

Aquí hay una variante de la secuencia de comandos y no se necesita raíz:

#!/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"


Corre arriba y luego presione O p Entrar . Ahora los procesos deben ser ordenados por su uso de intercambio.

Aquí hay una actualización ya que mi respuesta original no proporciona una respuesta exacta al problema como se señala en los comentarios. Desde el htop FAQ :

No es posible obtener el tamaño exacto del espacio de intercambio utilizado de un proceso. Top falsifica esta información haciendo SWAP = VIRT - RES, pero eso no es una buena métrica, porque otras cosas como la memoria de video también cuentan con VIRT (por ejemplo: top dice que mi proceso X está usando 81M de intercambio, pero también informa que mi sistema en su conjunto utiliza solo 2 M. de intercambio. Por lo tanto, no agregaré una columna de Intercambio similar a htop porque no conozco una forma confiable de obtener esta información (en realidad, no creo que sea posible obtener un número exacto, debido a las páginas compartidas).


Supongo que podría obtener una buena suposición ejecutando top y buscando procesos activos que usen mucha memoria. Hacer esto programáticamente es más difícil, solo mire los interminables debates sobre la heurística asesina de OOM de Linux.

El intercambio es una función de tener más memoria en uso activo de la que está instalada, por lo que generalmente es difícil echarle la culpa a un solo proceso. Si se trata de un problema continuo, la mejor solución es instalar más memoria o realizar otros cambios sistémicos.


En MacOSX, también ejecuta el comando top, pero necesita escribir "o", luego "vsize" y luego ENTER.


Sin embargo, dos variantes más:

Una variante de shell ! (No bash solamente)

Esto es exactamente igual que el script lolotux , pero sin ningún tipo de bifurcación a grep , awk o ps . ¡Esto es mucho más rápido!

Y dado que bash es uno de los shell más pobres en cuanto a rendimiento, se realizó un pequeño trabajo para garantizar que este script se ejecute bien bajo dash , busybox y algunos otros. Luego, ( gracias a Stéphane Chazelas ,) ¡vuelve a ser mucho más rápido!

#!/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

¡No se olvide de poner la cita doble "$PROGNAME" ! Ver el comentario de Stéphane Chazelas :

read FIELD PROGNAME < <(
    perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"

¡No intente echo $PROGNAME sin comillas dobles en un sistema sensible, y prepárese para matar el shell actual antes!

Y una version perl

A medida que se convierte en un script no tan simple , es hora de escribir una herramienta dedicada utilizando un lenguaje más eficiente.

#!/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;

podría correr con uno de

-c  sort by command name
-p  sort by pid
-m  sort by swap values
by default, output is sorted by status's vmsize

Adapté un script diferente en la web a esta larga frase de una sola línea:

 { 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 luego lanzo en un cronjob y redirigir la salida a un archivo de registro. La información aquí es la misma que para acumular las entradas Swap: en el archivo smaps, pero si quiere estar seguro, puede usar:

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

El resultado de esta versión está en dos columnas: pid, cantidad de intercambio. En la versión anterior, tr elimina los componentes no numéricos. En ambos casos, la salida está ordenada numéricamente por pid.


Otra variante del script evitando el loop en 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
  }'

El uso estándar es script.sh para obtener el uso por programa con un orden aleatorio (hasta cómo awk almacena sus hashes) o script.sh 1 para ordenar la salida por pid.

Espero haber comentado el código lo suficiente como para decir lo que hace.


Bash ha select para este propósito.

select result in Yes No Cancel
do
    echo $result
done




linux memory swap