Как узнать, какие процессы используют пространство подкачки в Linux? - PullRequest
227 голосов
/ 26 января 2009

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

Ответы [ 15 ]

283 голосов
/ 24 августа 2011

Лучший скрипт, который я нашел, находится на этой странице: 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"
100 голосов
/ 26 января 2009

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

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

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

53 голосов
/ 04 сентября 2012

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

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

Для первого вы можете запустить top и сделать заказ с помощью свопа (нажмите «Op»), для последнего вы можете запустить vmstat и искать ненулевые записи для «так».

9 голосов
/ 06 октября 2014

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

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

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

6 голосов
/ 01 сентября 2015

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

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

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

6 голосов
/ 27 июля 2012

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

5 голосов
/ 05 августа 2016

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

A вариант! (Не только 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"! См. комментарий Стефана Шазеласа :

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
3 голосов
/ 16 марта 2016

Я адаптировал другой веб-скрипт для этой длинной строки:

 { 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.

3 голосов
/ 19 января 2012

В MacOSX вы также запускаете команду top, но вам нужно набрать «o», затем «vsize», а затем «ENTER».

...