Як дізнатися, який процес використовує простір swap більше в Linux?
Як дізнатися, який процес використовує простір swap більше в Linux?
Відповіді:
Запустіть верх, а потім натисніть OpEnter. Тепер процеси слід сортувати за їхнім використанням.
Ось оновлення, оскільки моя оригінальна відповідь не дає точної відповіді на проблему, як зазначено в коментарях. Із поширених запитань htop :
Неможливо отримати точний розмір використовуваного простору swap процесу. Топ підробляє цю інформацію, роблячи SWAP = VIRT - RES, але це не є хорошим показником, оскільки інші речі, такі як відеопам'ять, також розраховуються на VIRT (наприклад: top говорить, що мій процес X використовує 81M свопу, але він також повідомляє, що моя система в цілому використовує лише 2M свопів. Тому я не додаватиму подібний стовпчик Swap в 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; вашому будку може чогось бракувати.
top
: northmost.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
та шукати ненульові записи для "так".
Команда вгорі також містить поле для відображення кількості несправностей сторінки для процесу. Процес з максимальними помилками сторінки буде процесом, який змінюється найбільше. Для довготривалих демонів можливо, що вони на початку мають велику кількість помилок сторінки, а потім кількість не збільшується. Тому нам потрібно спостерігати, чи збільшуються помилки сторінки.
Ще один варіант сценарію, уникаючи циклу в оболонці:
#!/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 вище коду 9 ascii. Це дає вигляд і відчуття "випадкового порядку". Я згоден з таблицею 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, сума swap. У вищенаведеній версії tr
смужки нечислових компонентів. В обох випадках вихід сортується чисельно за допомогою pid.
Я припускаю, що ви можете добре здогадатися, запустивши top
та шукаючи активні процеси, використовуючи багато пам’яті. Зробити це програмно важче --- просто подивіться на нескінченні дискусії про евристику вбивць Linux OOM.
Перекачування є функцією , що мають більше пам'яті в активному використанні , ніж встановлений, так що, як правило , важко звинуватити в цьому єдиному процесі. Якщо це проблема триває, найкраще рішення - встановити більше пам'яті або внести інші системні зміни.
Дає підсумки та відсотки для процесу за допомогою swap
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, другий стовпчик - це використання своп у KiB, а решта рядка - команда виконується. Ідентичні підрахунки свопів сортуються за pid.
Вище може випромінювати рядки типу
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
що просто означає, що процес з підпискою 15407 закінчився між переглядом його у списку /proc/
та читанням smaps
файлу процесу . Якщо це має значення для вас, просто додайте 2>/dev/null
до кінця. Зверніть увагу, що ви також потенційно втратите будь-яку іншу можливу діагностику.
У прикладі реального світу це змінює використання інших інструментів звітування ~ 40 Мб використання свопів для кожної дитини апаша, що працює на одному сервері, на фактичне використання від 7-3630 Кб, дійсно використане на одну дитину.