Как узнать, какие процессы используют пространство подкачки в Linux?

В Linux, как узнать, какой процесс использует пространство подкачки?

Ответ 1

Верните верх, затем нажмите O p Enter. Теперь процессы должны сортироваться по их использованию подкачки.

Вот обновление, так как мой первоначальный ответ не дает точного ответа на проблему, как указано в комментариях. Из htop FAQ:

Невозможно получить точный размер используемого пространства подкачки обработать. Top подделывает эту информацию, создавая SWAP = VIRT - RES, но это не очень хорошая метрика, потому что другие вещи, такие как видеопамять также рассчитывает на VIRT (например: top говорит, что мой X-процесс использует 81M, но он также сообщает, что моя система в целом использует только 2M свопа. Поэтому я не добавлю аналогичный столбец Swap в htop потому что я не знаю надежного способа получить эту информацию (на самом деле, Я не думаю, что можно получить точный номер из-за совместного использования страниц).

Ответ 2

Лучший script, который я нашел на этой странице: http://northernmost.org/blog/find-out-what-is-using-your-swap/

Здесь нужен один вариант script и не нужен корень:

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

Ответ 3

Вот еще один вариант script, но предназначенный для получения более читаемого вывода (вам нужно запустить его как 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}/";

Ответ 4

Не совсем ясно, имеете ли вы в виду, что вы хотите найти процесс, у которого больше всего страниц поменялось или обработано, из-за чего большинство страниц было заменено.

Для первого вы можете запустить top и упорядочить по swap (нажмите "Op" ), для последнего вы можете запустить vmstat и искать ненулевые записи для "so".

Ответ 5

Я заметил, что эта ветка довольно старая, но если вы случайно наткнулись на нее, как я и сделал, другой ответ: используйте smem.

Вот ссылка, которая сообщает вам, как установить и как ее использовать:

http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/

Ответ 6

Верхняя команда также содержит поле для отображения количества ошибок страницы для процесса. Процесс с максимальными ошибками страницы будет процессом, который чаще всего заменяет. Для длинных демонов может случиться, что они поначалу подвергаются большому количеству ошибок страниц, а число не увеличивается позже. Поэтому нам нужно наблюдать, увеличивается ли ошибка страниц.

Ответ 7

Другой вариант script, избегающий цикла в оболочке:

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

Надеюсь, я достаточно прокомментировал код, чтобы рассказать, что он делает.

Ответ 8

Еще два варианта:

Вариант ! (Не только bash)

Это в точности то же самое, что и скрипт lolotux, но без разветвления для grep, awk или ps. Это намного быстрее!

А поскольку является одним из самых плохих в отношении производительности, была проделана небольшая работа для обеспечения того, чтобы этот сценарий хорошо работал в , и некоторых других. Затем (благодаря Стефану Шазеласу) снова стать намного быстрее!

#!/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" двойную кавычку "$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 vmsize

Ответ 9

Я предполагаю, что вы могли бы получить хорошее предположение, запустив top и ища активные процессы, используя много памяти. Делать это программно сложнее - просто посмотрите на бесконечные дискуссии об эвристике киллера Linux OOM.

Подкачка - это функция большей памяти при активном использовании, чем установлено, поэтому обычно трудно обвинить ее в одном процессе. Если это постоянная проблема, лучшим решением является установка большего объема памяти или внесение других системных изменений.

Ответ 10

В MacOSX вы также запускаете верхнюю команду, но вам нужно ввести "o", затем "vsize", затем "ENTER".

Ответ 11

Я не знаю никакого прямого ответа, как определить, какой процесс использует пространство подкачки, однако эта ссылка может быть полезно. Еще один хороший здесь

Кроме того, используйте хороший инструмент, такой как htop, чтобы узнать, какие процессы используют много памяти и сколько используется своп.

Ответ 12

iotop - очень полезный инструмент. Он дает живую статистику ввода-вывода и использования swap для каждого процесса/потока. По умолчанию он показывает поток, но вы можете сделать iotop -P для получения информации о процессе. По умолчанию это недоступно. Возможно, вам придется установить через rpm/apt.

Ответ 13

Я адаптировал другой script в Интернете к этому длинному однострочному слою:

 { 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 amount. В приведенной выше версии tr разбивает нечисловые компоненты. В обоих случаях вывод сортируется численно pid.

Ответ 15

Здесь версия, которая выводит то же самое, что и скрипт @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