web-dev-qa-db-ja.com

どのプロセスがLinuxでスワップ空間を使用しているかを調べる方法は?

Linuxでは、どのプロセスがスワップスペースをもっと使用しているのかをどのように確認できますか?

227
Shameem

topを実行してを押す OpEnter。今プロセスはスワップの使用法でソートされるべきです。

コメントで指摘されているように、私の最初の答えでは問題に対する正確な答えが得られないため、これが更新です。 htop FAQ から:

プロセスの使用済みスワップスペースの正確なサイズを取得することは不可能です。 TopはSWAP = VIRT - RESにすることでこの情報を偽造しますが、ビデオメモリのような他のものもVIRTを頼りにしているのでこれは良い基準ではありませんシステム全体で2Mのスワップしか使用していないと報告していますので、この情報を取得するための信頼できる方法がわからないため、htopに同じようなSwapカラムを追加しません共有ページのため正確な数).

100
David Holm

私が見つけた最高のスクリプトはこのページです: http://northernmost.org/blog/find-out-what-is-using-your-swap/

これはスクリプトの変種の1つで、rootは必要ありません。

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

これはスクリプトの別の変種ですが、より読みやすい出力を提供することを意図しています(正確な結果を得るには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}/";
53
j3nda

大部分のページがスワップアウトされたプロセス、または大部分のページがスワップアウトされたプロセスを探したいのかどうかは、完全には明らかではありません。

最初の場合はtopを実行してswapで並べ替え( 'Op'を押す)、後者の場合はvmstatを実行して 'so'のゼロ以外のエントリを探すことができます。

10
Ronny Vindenes

私はこのスレッドがかなり古くなっていることに気づきました、しかし私がちょうどしたようにあなたがそれにつまずくことが偶然にあるならば、もう一つの答えがあります。

これは、インストール方法と使用方法の両方を説明しているリンクです。

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

9
Tom

シェル内のループを回避するもう1つのスクリプト亜種:

#!/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
  }'

標準的な使用法は、プログラムごとの使用法をランダムな順序(awkがハッシュを格納する方法まで)で取得する場合はscript.sh、出力をpidでソートする場合はscript.sh 1です。

私はそれが何をするのかを伝えるのに十分なコードにコメントしたことを願っています。

6
Tensibai

Topコマンドには、プロセスのページフォルト数を表示するためのフィールドも含まれています。最大ページフォルトを伴うプロセスは、最もスワップしているプロセスです。長期実行デーモンの場合、最初に多数のページ不在が発生し、後でその数が増えないことがあります。そのため、ページ違反が増えているかどうかを確認する必要があります。

6
Amol Kulkarni

まだ2つの亜種:

A Shell バリアント! (bashだけではありません)

これは lolotux script とまったく同じですが、grepawk、またはpsへの分岐はありません。これはずっと速いです!

そして bash がパフォーマンスに関して最も貧弱なものの1つ--- Shell このスクリプトがうまく動作するようにするために少し作業が行われました dashbusybox その他それでは、( StéphaneChazelasに感謝 、)、また早くなります。

#!/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"を忘れないでください。 StéphaneChazelas's comment を参照してください。

read FIELD PROGNAME < <(
    Perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"

賢明なシステムでは、二重引用符なしでecho $PROGNAMEを試してはいけません。以前に現在のシェルを強制終了する準備をしてください。

そして Perl バージョン

これがそれほど単純ではないスクリプトになるにつれて、より効率的な言語を使用して専用のツールを作成する時期が来ています。

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

私はこの長いワンライナーにWeb上の別のスクリプトを適用しました。

 { 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に投げ、ログファイルに出力をリダイレクトします。ここの情報はsmapsファイルにSwap:エントリーを蓄積するのと同じですが、確かにしたいのなら、あなたは使うことができます:

{ 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; }

このバージョンの出力は2つの列にあります:pid、スワップ量。上記のバージョンでは、trは数値以外の要素を取り除きます。どちらの場合も、出力はpidによって数値順にソートされます。

3
Otheus

MacOSXでは、topコマンドも実行しますが、 "o"、 "vsize"、そしてENTERと入力する必要があります。

3
Alexis

topを実行して大量のメモリを使用しているアクティブなプロセスを探すことで推測できると思います。これをプログラム的に行うのはより困難です。LinuxOOMのキラーヒューリスティックに関する無限の議論を見てください。

スワッピングは、インストールされているよりもアクティブ使用中のメモリの量が多いため、1つのプロセスでそれを責めることは通常困難です。それが継続的な問題である場合、最善の解決策はより多くのメモリを取り付けるか、または他の体系的な変更を加えることです。

2
dmckee

スワップを使用してプロセスの合計と割合を示します

smem -t -p

enter image description here

出典: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/

1
Soumya Boral

iotopはとても便利なツールです。これは、プロセス/スレッドごとのI/Oとスワップ使用率のライブ統計を示します。デフォルトではスレッドごとに表示されますが、プロセスごとの情報を取得するにはiotop -Pを実行できます。これはデフォルトでは利用できません。 rpm/aptでイ​​ンストールする必要があるかもしれません。

1
sunil

どのプロセスがスワップ空間を使用しているのかを正確に見つける方法として直接的な答えはわかりませんが、このリンクは 役に立つ になります。もう一つの良いものは ここを越えて

また、htopのような優れたツールを使用して、どのプロセスが大量のメモリを使用しているか、および全体的に使用されているスワップの量を確認します。

1
Jean Azzopardi

これは@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
0
Dmitry z