En Linux, ¿cómo puedo saber qué proceso está usando más el espacio de intercambio?
En Linux, ¿cómo puedo saber qué proceso está usando más el espacio de intercambio?
Respuestas:
Corre arriba y luego presiona OpEnter. Ahora los procesos deben ordenarse 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. De las preguntas frecuentes de htop :
No es posible obtener el tamaño exacto del espacio de intercambio utilizado de un proceso. Top falsifica esta información al hacer SWAP = VIRT - RES, pero esa no es una buena métrica, porque otras cosas como la memoria de video también cuenta en VIRT (por ejemplo: top dice que mi proceso X está utilizando 81M de intercambio, pero también informa que mi sistema en su conjunto está usando solo 2M 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).
El mejor script que encontré está en esta página: http://northernmost.org/blog/find-out-what-is-using-your-swap/
Aquí hay una variante del script y no se necesita root:
#!/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
738932
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
para Debian / RH 6x +, Arch, Ubuntu (RH 5x tiene VmSize
) ( fuente ). Al igual que @dgunchev, da mucho menos intercambio total que free
. @Tensibai no funciona en Arch; tu awk puede carecer de algo.
top
: northernmost.org/blog/swap-usage-5-years-later
Aquí hay otra variante de la secuencia de comandos, pero destinada a proporcionar una salida más legible (debe ejecutar esto como raíz 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}/";
args
en lugar de comm
en el ps
comando ya que tengo una gran cantidad de procesos con el mismo nombre pero diferentes argumentos (un manojo de procesos pitón gunicorn). Es decir:ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
awk ' /VmSwap/ { print $2 }'
Me di cuenta de que este hilo es bastante antiguo, pero si te topas con él, como acabo de hacer, otra respuesta es: usa smem.
Aquí hay un enlace que le indica cómo instalarlo y cómo usarlo:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
No está del todo claro si quiere decir que desea encontrar el proceso que ha intercambiado la mayoría de las páginas o el proceso que ha provocado el intercambio de la mayoría de las páginas.
Para el primero, puede ejecutar top
y ordenar por intercambio (presione 'Op'), para el último puede ejecutar vmstat
y buscar entradas que no sean cero para 'so'.
El comando superior también contiene un campo para mostrar el número de fallas de página para un proceso. El proceso con errores máximos de página sería el proceso que más se intercambia. Para los demonios de larga ejecución, es posible que incurran en un gran número de fallas de página al principio y que el número no aumente más adelante. Por lo tanto, debemos observar si las fallas de la página están aumentando.
Otra variante de script que evita el bucle 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
obtener el uso por programa con orden aleatorio (hasta cómo awk
almacena sus hashes) u script.sh 1
ordenar la salida por pid.
Espero haber comentado el código lo suficiente como para decir lo que hace.
bash
expande los directorios de forma ordenada (léxico, no numérico). El orden aleatorio depende de cómo awk
almacena sus matrices (tabla hash) y cómo las for p in pname
recupera.
/proc/1/status
viene después /proc/1992/status
y que /
tiene un código ASCII por encima del código ASCII 9. Esto le da un aspecto de "orden aleatorio" y también estoy de acuerdo. Estoy de acuerdo con la tabla de hash awk , Tomé un atajo aquí. Siéntase libre de editar la respuesta para mantener la atribución en el historial de edición.
/proc/1/status
no vendría después /proc/1992/status
en la configuración regional C donde el orden se basa en el valor del byte. Lo hace en su configuración regional (o en mi en_GB.UTF-8
en un sistema GNU), porque /
se ignora en primera instancia en el algoritmo de clasificación (y se s
ordena después 9
). Comparar 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
. En entornos locales que no sean C
, el orden de clasificación generalmente no se basa en el valor de byte.
Debido a que top
o htop
no se puede instalar en sistemas pequeños, la navegación /proc
siempre es posible.
Incluso en sistemas pequeños, encontrará shell
...
Esto es exactamente lo mismo que el script lolotux , pero sin ningún tenedor para grep
, awk
o ps
. ¡Esto es mucho más rápido!
Y como intento es uno de los más pobres cáscara con respecto al rendimiento, se realizó un pequeño trabajo para garantizar que este script se ejecute bien bajo guión, busyboxy alguna otra Entonces, ( 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 te olvides de comillas dobles "$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 lo intentes echo $PROGNAME
sin comillas dobles en un sistema sensible y prepárate para matar el shell actual antes!
A medida que esto se convierte en un guión no tan simple , llega el momento de escribir una herramienta dedicada mediante el uso de 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
:
, barras invertidas, comodines ni caracteres de control.
[1-9]
antes *
para contar solo los caminos numerados (no self
, ni thread-self
)
Name
entrada en /proc/*/status
codifica algunos de esos valores de bytes. Prueba por ejemplo perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Debido a que es tan corto, el daño que se puede hacer con cosas como perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
es limitado cuando olvida citar sus variables.
Adapte un guión diferente en la web a esta larga 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 arrojo a un cronjob y redirijo la salida a un archivo de registro. La información aquí es lo mismo que acumular las Swap:
entradas en el archivo smaps, pero si quieres estar seguro, puedes 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, las tr
tiras de los componentes no numéricos. En ambos casos, la salida se ordena numéricamente por pid.
Supongo que podrías adivinar si ejecutas top
y buscas procesos activos con mucha memoria. Hacer esto programáticamente es más difícil, solo mira los interminables debates sobre la heurística asesina OOM de Linux.
El intercambio es una función de tener más memoria en uso activo de lo que está instalado, por lo que generalmente es difícil culparlo de 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.
Proporciona totales y porcentajes para el proceso mediante intercambio
smem -t -p
Fuente: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
No conozco ninguna respuesta directa sobre cómo encontrar exactamente qué proceso está utilizando el espacio de intercambio, sin embargo, este enlace puede ser útil . Otra buena está por aquí
Además, use una buena herramienta como htop para ver qué procesos están usando mucha memoria y cuánto intercambio en general se está utilizando.
iotop
Es una herramienta muy útil. Ofrece estadísticas en vivo de E / S y uso de intercambio por proceso / subproceso. De manera predeterminada, se muestra por hilo, pero puede hacerlo iotop -P
para obtener información por proceso. Esto no está disponible por defecto. Puede que tenga que instalar a través de rpm / apt.
Aquí hay una versión que genera lo mismo que el script de @loolotux, pero es mucho más rápido (aunque menos legible). Ese ciclo toma alrededor de 10 segundos en mi máquina, mi versión toma 0.019 s, lo que me importó porque quería convertirlo en una página 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
Desde el parche del kernel del año 2015 que agrega SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ) finalmente se puede obtener un conteo de intercambio proporcional, lo que significa que si un proceso ha cambiado mucho y luego se bifurca, ambos procesos se bifurcan se informará que intercambiará el 50% cada uno. Y si cualquiera de las dos se bifurca, cada proceso cuenta el 33% de las páginas intercambiadas, por lo que si cuenta todos esos usos de intercambio juntos, obtendrá un uso de intercambio real en lugar del valor multiplicado por el recuento de procesos.
En 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 primera columna es pid, la segunda columna es el uso de intercambio en KiB y el resto de la línea se ejecuta el comando. Los recuentos de intercambio idénticos se ordenan por pid.
Arriba puede emitir líneas como
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
lo que simplemente significa que el proceso con pid 15407 terminó entre verlo en la lista /proc/
y leer el smaps
archivo de proceso . Si eso te importa, simplemente agrégalo 2>/dev/null
al final. Tenga en cuenta que potencialmente también perderá cualquier otro diagnóstico posible.
En el caso de ejemplo del mundo real, esto cambia otras herramientas que informan ~ 40 MB de uso de intercambio para cada niño apache que se ejecuta en un servidor al uso real de entre 7-3630 KB realmente usado por niño.