No Linux, como descubro qual processo está usando mais o espaço de troca?
No Linux, como descubro qual processo está usando mais o espaço de troca?
Respostas:
Corra para cima e pressione OpEnter. Agora os processos devem ser classificados pelo uso de troca.
Aqui está uma atualização, pois minha resposta original não fornece uma resposta exata para o problema, conforme apontado nos comentários. Na FAQ do htop :
Não é possível obter o tamanho exato do espaço de troca usado de um processo. O Top falsifica essas informações criando SWAP = VIRT - RES, mas essa não é uma boa métrica, porque outras coisas, como a memória de vídeo, também contam com o VIRT (por exemplo: top diz que meu processo X está usando 81M de swap, mas também relata que meu sistema como um todo está usando apenas 2M de swap.Portanto, não adicionarei uma coluna Swap semelhante ao htop porque não conheço uma maneira confiável de obter essas informações (na verdade, acho que não é possível obter um número exato, devido às páginas compartilhadas).
O melhor script que encontrei está nesta página: http://nouthernmost.org/blog/find-out-what-is-using-your-swap/
Aqui está uma variante do script e nenhuma raiz é necessária:
#!/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
, enquanto shows gratuitos 738932
como usado ...
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 possui VmSize
) ( fonte ). Como @dgunchev, ele oferece muito menos troca total do que free
. @Tensibai não funciona no Arch; seu awk pode faltar alguma coisa.
top
: northernmost.org/blog/swap-usage-5-years-later
Aqui está outra variante do script, mas destinada a fornecer uma saída mais legível (você precisa executá-lo como root para obter resultados exatos):
#!/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
vez de comm
no ps
comando, pois tenho muitos processos com o mesmo nome, mas com argumentos diferentes (vários processos python gunicorn). ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
poderia ser simplificado comoawk ' /VmSwap/ { print $2 }'
Notei que esse tópico é bastante antigo, mas se você o encontrar, como eu acabei de fazer, outra resposta é: use smem.
Aqui está um link que informa sobre como instalá-lo e como usá-lo:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Não está totalmente claro se você quer encontrar o processo com a maioria das páginas trocadas ou o processo que causou a troca de muitas páginas.
No primeiro, você pode executar top
e ordenar por troca (pressione 'Op'); no último, você pode executar vmstat
e procurar entradas diferentes de zero para 'so'.
O comando top também contém um campo para exibir o número de falhas de página para um processo. O processo com falhas máximas de página seria o processo que mais trocaria. Para daemons de longa execução, pode ser que eles apresentem um grande número de falhas de página no início e o número não aumente posteriormente. Portanto, precisamos observar se as falhas da página estão aumentando.
Outra variante de script que evita o loop no 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
}'
O uso padrão é script.sh
obter o uso por programa em ordem aleatória (até como awk
armazena seus hashes) ou script.sh 1
classificar a saída por pid.
Espero ter comentado o código o suficiente para dizer o que ele faz.
bash
expande os diretórios de maneira ordenada (lexical, não numérica). A ordem aleatória se resume a como awk
as matrizes são armazenadas (tabela de hash) e como as for p in pname
recupera.
/proc/1/status
vem depois /proc/1992/status
e que /
tem um código ASCII acima do código ASCII 9. Isso também dá uma aparência e uma "ordem aleatória". Concordo com a tabela de hash awk , tomei um atalho aqui Sinta-se livre para editar a resposta para manter a atribuição no histórico de edições..
/proc/1/status
não viria depois /proc/1992/status
na localidade C, em que o pedido é baseado no valor do byte. Isso ocorre no seu código de idioma (ou no meu en_GB.UTF-8
em um sistema GNU), porque /
é ignorado em primeira instância no algoritmo de agrupamento (e s
depois 9
). Compare printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
com printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
. Em locais diferentes C
, a ordem de classificação geralmente não se baseia no valor do byte.
Como top
ou htop
não pôde ser instalado em sistemas pequenos, a navegação /proc
sempre é possível.
Mesmo em pequenos sistemas, você encontrará um shell
...
É exatamente o mesmo que o script lolotux , mas sem nenhum garfo para grep
, awk
ou ps
. Isso é muito mais rápido!
E como festança é um dos mais pobres Concha em relação ao desempenho, foi feito um pouco de trabalho para garantir que esse script funcione bem sob traço, busyboxe alguns outros. Então, ( graças a Stéphane Chazelas ,) tornou-se muito mais rápido novamente!
#!/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ão se esqueça de citar duas vezes "$PROGNAME"
! Veja o comentário de Stéphane Chazelas :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
Não tente echo $PROGNAME
sem aspas duplas no sistema sensível e esteja pronto para matar o shell atual antes!
Como isso se tornou um script não tão simples , está chegando a hora de escrever uma ferramenta dedicada usando uma linguagem mais 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;
poderia correr com um dos
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
, barra invertida, curinga ou controle.
[1-9]
antes *
para contar apenas os caminhos numerados (não self
, nem thread-self
) #
Name
entrada /proc/*/status
codifica alguns desses valores de bytes. Tente por exemplo perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Por ser tão curto, o dano que pode ser causado com coisas do tipo perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
é limitado quando você esquece de citar suas variáveis.
Eu adaptei um script diferente na web para esse longo artigo:
{ 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 eu joguei em um cronjob e redirecionei a saída para um arquivo de log. As informações aqui são as mesmas de acumular as Swap:
entradas no arquivo smaps, mas se você quiser ter certeza, pode 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; }
A saída desta versão está em duas colunas: pid, quantidade de swap. Na versão acima, tr
retira os componentes não numéricos. Nos dois casos, a saída é classificada numericamente por pid.
Suponho que você poderia adivinhar executando top
e procurando processos ativos usando muita memória. Fazer isso programaticamente é mais difícil - basta olhar para os intermináveis debates sobre as heurísticas do killer do Linux OOM.
A troca é uma função de ter mais memória em uso ativo do que a instalada, por isso é geralmente difícil culpá-la em um único processo. Se houver um problema contínuo, a melhor solução é instalar mais memória ou fazer outras alterações sistêmicas.
Dá totais e porcentagens para o processo usando swap
smem -t -p
Fonte: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Não conheço nenhuma resposta direta sobre como encontrar exatamente qual processo está usando o espaço de troca, no entanto, esse link pode ser útil . Outra boa é aqui
Além disso, use uma boa ferramenta como a htop para ver quais processos estão usando muita memória e quanto swap global está sendo usado.
iotop
é uma ferramenta muito útil. Ele fornece estatísticas ao vivo de E / S e troca de uso por processo / encadeamento. Por padrão, ele é exibido por thread, mas você pode fazer isso iotop -P
para obter informações por processo. Isso não está disponível por padrão. Você pode ter que instalar via rpm / apt.
Aqui está uma versão que gera o mesmo que o script do @loolotux, mas é muito mais rápida (embora menos legível). Esse loop leva cerca de 10 segundos na minha máquina, minha versão leva 0,019 s, o que era importante para mim porque eu queria transformá-lo em uma 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 o ano de 2015, o patch do kernel que adiciona SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ) pode-se finalmente obter uma contagem proporcional de trocas, o que significa que se um processo tiver trocado muito e forjado, os dois processos bifurcados será relatado para trocar 50% cada. E, se um dos dois for bifurcado, cada processo contará 33% das páginas trocadas; portanto, se você contar todos esses usos de troca juntos, obterá um uso real da troca, em vez do valor multiplicado pela contagem do processo.
Em resumo:
(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)
A primeira coluna é pid, a segunda coluna é o uso de swap no KiB e o restante da linha é o comando sendo executado. Contagens de troca idênticas são classificadas por pid.
Acima pode emitir linhas como
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
o que significa simplesmente que o processo com o pid 15407 terminou entre vê-lo na lista /proc/
e ler o smaps
arquivo do processo . Se isso importa para você, basta adicionar 2>/dev/null
até o fim. Observe que você também perderá outros diagnósticos possíveis.
No caso de exemplo do mundo real, isso altera outras ferramentas que relatam ~ 40 MB de uso de troca para cada filho apache em execução em um servidor para uso real entre 7-3630 KB realmente usado por filho.