В Linux, как мне узнать, какой процесс больше использует пространство подкачки?
В Linux, как мне узнать, какой процесс больше использует пространство подкачки?
Ответы:
Запустите сверху, затем нажмите OpEnter. Теперь процессы должны быть отсортированы по их использованию подкачки.
Вот обновление, так как мой оригинальный ответ не дает точного ответа на проблему, как указано в комментариях. Из htop FAQ :
Невозможно получить точный размер используемого пространства подкачки процесса. Top подделывает эту информацию, делая SWAP = VIRT - RES, но это не очень хорошая метрика, потому что другие вещи, такие как видеопамять, тоже учитываются в VIRT (например: top говорит, что мой процесс X использует 81M подкачки, но также сообщает, что моя система в целом использует только 2M подкачки. Поэтому я не буду добавлять аналогичный столбец подкачки в htop, потому что я не знаю надежного способа получить эту информацию (на самом деле, я не думаю, что это возможно получить точное число, из-за общих страниц).
Лучший сценарий, который я нашел, находится на этой странице: http://northernmost.org/blog/find-out-what-is-using-your-swap/
Вот один из вариантов скрипта и без рута:
#!/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
для Debian / RH 6x +, Arch, Ubuntu (RH 5x имеет VmSize
) ( источник ). Как и @dgunchev, он дает гораздо меньше общего свопа, чем free
. @Tensibai не работает на Arch; в вашем awk может чего-то не хватать
top
: northernmost.org/blog/swap-usage-5-years-later
Вот еще один вариант скрипта, но он предназначен для получения более читабельного вывода (вам нужно запустить его как root, чтобы получить точные результаты):
#!/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
вместо comm
в ps
команде , так как у меня есть много процессов , с тем же именем , но с разными аргументами (связка питон gunicorn процессов). ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
можно упростить какawk ' /VmSwap/ { print $2 }'
Я заметил, что эта ветка довольно старая, но если вы случайно наткнулись на нее, как я только что сделал, другой ответ: используйте smem.
Вот ссылка, которая расскажет вам, как установить его и как его использовать:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Не совсем понятно, хотите ли вы найти процесс, у которого было выгружено большинство страниц, или процесс, который вызвал замену большинства страниц.
Для первого вы можете запустить top
и сделать заказ путем свопинга (нажмите «Op»), для последнего вы можете запустить vmstat
и искать ненулевые записи для «так».
Команда top также содержит поле для отображения количества сбоев страниц для процесса. Процесс с максимальным количеством сбоев страниц будет процессом, который обменивается больше всего. Для длительно работающих демонов может случиться так, что они вначале сталкиваются с большим количеством сбоев страниц, и в дальнейшем это число не увеличивается. Таким образом, мы должны наблюдать, увеличивается ли количество ошибок на странице.
Еще один вариант сценария, позволяющий избежать цикла в оболочке:
#!/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
}'
Стандартное использование состоит в том, script.sh
чтобы получить использование для каждой программы в случайном порядке (вплоть до того, как awk
хранит ее хеши) или script.sh 1
отсортировать вывод по pid.
Надеюсь, я прокомментировал код достаточно, чтобы рассказать, что он делает.
bash
каталоги расширяются отсортированным способом (лексическим, а не числовым). Случайный порядок сводится к тому, как awk
хранить свои массивы (хеш-таблицу) и как for p in pname
их извлекать.
/proc/1/status
следует из того, /proc/1992/status
что /
код ascii выше кода ascii 9. Это также дает внешний вид и случайный порядок). Я согласен с хеш-таблицей awk Я взял ярлык здесь. Не стесняйтесь редактировать ответ, чтобы сохранить атрибуцию в истории редактирования.
/proc/1/status
не будет следовать /proc/1992/status
в локали C, где порядок основан на значении байта. Это происходит в вашей локали (или в моей en_GB.UTF-8
системе GNU), потому /
что в алгоритме сортировки в первом случае игнорируется (и s
сортируется после 9
). Сравните printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
с printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
. В других локалях C
порядок сортировки обычно не основан на значении байта.
Поскольку top
или htop
могут быть не установлены в небольших системах, просмотр /proc
всегда возможен.
Даже в небольших системах вы найдете shell
...
Это точно так же , чем lolotux сценарий , но без какой - либо вилки grep
, awk
или ps
. Это намного быстрее!
И, как удар один из самых бедных оболочка Что касается производительности, была проделана небольшая работа, чтобы этот скрипт хорошо работал под тир, BusyBoxи некоторые другие. Затем ( благодаря Стефану Шазеласу ) снова стать намного быстрее!
#!/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
Не забудьте двойную кавычку "$PROGNAME"
! Смотрите комментарий Стефана Шазеля :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
Не пытайтесь echo $PROGNAME
без двойной кавычки на разумной системе, и будьте готовы убить текущую оболочку раньше!
Поскольку это становится не таким простым сценарием, настало время написать специальный инструмент, используя более эффективный язык.
#!/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;
может бежать с одним из
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
, обратной косой черты, подстановочных знаков или управляющих символов.
[1-9]
ранее *
для подсчета только пронумерованных путей (нет self
, ни thread-self
)
Name
Запись в /proc/*/status
кодирует некоторые из этих значений байтов. Попробуйте, например perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Поскольку он настолько короткий, ущерб, который может быть нанесен такими вещами, perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
ограничен, если вы забудете процитировать свои переменные.
Я адаптировал другой сценарий в Интернете для этой длинной строки:
{ 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 ; }
Который я тогда бросаю в cronjob и перенаправляю вывод в файл журнала. Информация здесь та же, что и при накоплении Swap:
записей в файле smaps, но если вы хотите быть уверены, вы можете использовать:
{ 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; }
Вывод этой версии в двух столбцах: pid, сумма обмена. В вышеприведенной версии tr
полосы не числовые компоненты. В обоих случаях выходные данные сортируются численно по pid.
Я полагаю, что вы могли бы получить хорошее предположение, запустив top
и ища активные процессы, использующие много памяти. Делать это программно сложнее - просто посмотрите на бесконечные споры об эвристике убийцы Linux OOM.
Подкачка является функцией наличия большего количества памяти в активном использовании, чем установлено, поэтому обычно трудно обвинить это в одном процессе. Если это постоянная проблема, лучшим решением будет установка дополнительной памяти или внесение других системных изменений.
Дает итоги и проценты за процесс с использованием свопа
smem -t -p
Источник: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
Я не знаю ни одного прямого ответа о том, как точно определить, какой процесс использует пространство подкачки, однако эта ссылка может оказаться полезной . Еще один хороший здесь
Кроме того, используйте хороший инструмент, такой как htop, чтобы увидеть, какие процессы используют много памяти и сколько общего объема подкачки используется.
iotop
это очень полезный инструмент. Он дает оперативную статистику ввода / вывода и использования свопа для процесса / потока. По умолчанию он показывает для потока, но вы можете сделать, iotop -P
чтобы получить информацию о процессе. Это не доступно по умолчанию. Возможно, вам придется установить через rpm / apt.
Вот версия, которая выводит то же самое, что и скрипт @loolotux, но намного быстрее (хотя и менее читабелен). Этот цикл занимает около 10 секунд на моей машине, моя версия занимает 0,019 с, что имело значение для меня, потому что я хотел превратить его в страницу 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
Начиная с исправления ядра 2015 года, которое добавляет SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ), можно наконец получить пропорциональный счет подкачки, что означает, что если процесс поменялся много раз, а затем разветвился, оба разветвленных процесса будет сообщено о свопе на 50% каждый. И если любой из них затем разветвляется, то каждый процесс считается 33% переставленных страниц, поэтому, если вы посчитаете все эти операции подкачки вместе, вы получите реальное использование подкачки вместо значения, умноженного на количество процессов.
Коротко:
(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)
Первый столбец pid, второй столбец - использование свопа в КиБ, а остальная часть строки - выполнение команды. Идентичные числа свопа отсортированы по pid.
Выше могут испускать линии, такие как
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
это просто означает, что процесс с pid 15407 закончился между его отображением в списке /proc/
и чтением smaps
файла процесса . Если это важно для вас, просто добавьте 2>/dev/null
в конец. Обратите внимание, что вы потенциально можете потерять любую другую возможную диагностику.
В примере с реальным миром это меняет другие инструменты, сообщающие о ~ 40 МБ использования подкачки для каждого дочернего элемента apache, работающего на одном сервере, на фактическое использование между 7-3630 КБ, реально используемыми для каждого дочернего элемента.