Linuxでスワップスペースを使用しているプロセスを見つける方法は?


240

Linuxで、どのプロセスがスワップスペースをより多く使用しているのかをどのように確認しますか?


30
あなたの受け入れられた答えは間違っています。それを実際に正しいlolotuxの回答に変更することを検討してください。
jterrace

@jterraceは正しいです。一番上のSWAP列の値の合計ほどのスワップ領域はありません。
akostadinov 2012

1
iotopは非常に便利なコマンドで、ioのライブ統計とプロセス/スレッドごとのスワップ使用状況を表示します
sunil

@jterrace、その日の受け入れられた答えが間違っている人を述べること検討してください。6年後、David Holmの回答(今日のところ現在受け入れられているもの)と他の回答のどちらを参照しているかは、残りの人にはわかりません。(まあ、あなたはデビッド・ホルムの答えが間違っているとも言ったので、彼の答えへのコメントとして...それでおそらくあなたは彼のことを意味したと思います。)
Don Hatch

回答:


106

topを実行し、を押しOpEnterます。これで、プロセスはスワップの使用法でソートされます。

コメントで指摘されているように、私の元の答えは問題に対する正確な答えを提供していないため、ここに更新があります。htop FAQから:

プロセスの使用済みスワップ領域の正確なサイズを取得することはできません。トップはSWAP = VIRT-RESにすることでこの情報を偽造していますが、VIRTのビデオメモリ数などの他の要素も同様であるため、これは適切なメトリックではありません(たとえば、トップは、Xプロセスが81Mのスワップを使用していると言いますが、それもまたシステム全体で2Mのスワップのみを使用していると報告します。したがって、この情報を取得するための信頼できる方法がわからないため、同様のスワップ列をhtopに追加しません(実際、取得することはできないと思います共有ページのため、正確な数)。


137
ドキュメントから、一番上のSWAP列は、現在実際にプロセスがスワップされている量ではなく、プロセス全体がスワップアウトされた場合に必要なスワップ量を示しているようです。短時間の検索でわかることから、現時点でどのプロセスがどれだけスワップアウトされているかを判断する方法はありません。このため、htopの作成者はそのような列への入力を拒否します(CNSWAPおよびNSWAP列は表示されますが、私のマシンでは何も実行していないようです)。htop.sourceforge.net
yukondude 2009

6
@yukondudeは正しい、上部のSWAP列は単なるVIRT-RESであり、この情報はこのコンテキストでは役に立たないものです。マップされたビデオRAMの共有メモリなどの補償はありません。また、すべてのメモリがプロセスによってまだ参照されていない可能性があります。この場合、OSが完全なバイナリをディスクからメモリに読み取る必要はないため、RESの値にはメモリのこの部分は含まれません。
Bart

できればもっと賛成します。これは私のベーコンを救っています!
atrain

ありがたいことにそれが@jterraceのコメントです:)(確かにそれらを読む必要があります:S ...どの列車が何を指しているのかわからない、私はそれがyukondudeであることを願っています)
AJP

11
コメントが機能しなくなった場合:topの最近のバージョンでは、ソートフィールドを選択するためのキーとして「O」が設定されなくなったようです。?を使用する場合 キー実際のプログラム名とバージョンを確認できます。procps-ngが最新バージョンです。これは、Debian、Fedora、openSUSEによる分岐です:gitorious.org/procps。SWAP列でソートを実行する場合は、「f」キーを使用してフィールドを表示し、矢印キーを使用してSWAPに移動し、「s」を使用してソートを設定してから、「q」を使用します。
Pieter VN、

294

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

これはスクリプトの1つのバリアントであり、ルートは必要ありません。

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

リンクが切れ
dolanormisc

4
おかしいけど、Overall swap used: 260672 KB無料のショー738932は慣れていますが…
Doncho Gunchev

23
同じ出力が10倍速くなります:for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -nDebian / RH 6x +、Arch、Ubuntu(RH 5xにはVmSize)(ソース)。@dgunchevと同様に、合計スワップはに比べてはるかに少なくなりfreeます。@TensibaiはArchでは機能しません。あなたのawkは何かを欠いているかもしれません。
tuk0z 2015年

1
このスクリプトのノーフォークバージョンをご覧ください。
F.ハウリ16

3
著者は、それを使用してそれを行う方法についてのフォローアップ投稿がありますtopnorthernmost.org/blog/swap-usage-5-years-later
Jack Valmadre 2017

53

これはスクリプトの別のバリアントですが、より読みやすい出力を提供するためのものです(正確な結果を得るには、これを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}/";

2
とても素晴らしいスクリプトです。lolotuxと同じ情報を提供しますが、より読みやすい方法で提供されます。
Philipp Wendler

優れた出力。ありがとう。
ブライアンクライン2013年

2
私が変更した唯一のことは、同じ名前で引数が異なる多くのプロセス(python gunicornプロセスの束)があるため、コマンドのargs代わりにを使用することです。すなわち:commpsps -p $PID -o args --no-headers
mgalgs 2014

1
サイドノートは次のgrep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'ように簡略化できますawk ' /VmSwap/ { print $2 }'
Tensibai

12

このスレッドはかなり古いことに気づきましたが、偶然見つけた場合は、先ほどと同じように、smemを使用してください。

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

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


これはいいです PIDが追加されたスワップの使用法でソートされたprocを表示するために、この記事の改作バージョンを以下に示します。do awk '/ ^ Pid | VmSwap | Name / {printf $ 2 "" $ 3} END {print ""}' $ file; 完了| ソート-k 3 -n -r | 少ない
スタンブラジェスキー2017

/ proc / [1-9] * / statusをグロブして、いくつかの特別な/ procエントリを除外する必要があります。また、並べ替え引数を-rnk3として組み合わせることができます
dland

10

ほとんどのページがスワップアウトされたプロセス、またはほとんどのページがスワップアウトされたプロセスを見つける必要があるかどうかは、完全には明らかではありません。

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


6

topコマンドには、プロセスのページフォールトの数を表示するフィールドも含まれています。ページフォールトが最大のプロセスは、最もスワッピングしているプロセスです。長時間実行されるデーモンの場合、最初に多数のページフォールトが発生し、後でその数が増加しない場合があります。したがって、ページフォールトが増加しているかどうかを監視する必要があります。


6

シェルでのループを回避する別のスクリプトバリアント:

#!/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でソートすることです。

私はコードが何をするのかを説明するのに十分なだけコメントを付けたと思います。


1
bashソートされた方法でディレクトリを展開することに注意してください(数値ではなく字句)。ランダムな順序はawk、配列(ハッシュテーブル)の格納方法とfor p in pname取得方法に依存します。
Stephane Chazelas 16

@StephaneChazelasまあ、それは語彙的でさえない、それはasciiコードのソートです(/proc/1/status後に/proc/1992/status続く/ように、9のasciiコードの上にasciiコードがあります。これは「ランダムな順序」のルックアンドフィールも提供します。awkハッシュテーブルに同意します) 、ここでショートカットを作成しました。回答を編集して、帰属を編集履歴に残してください
Tensibai

1
/proc/1/status/proc/1992/status順序がバイト値に基づいているCロケールでは、後にはなりません。照合アルゴリズムの最初のインスタンスでは無視される(そしての後にソートされるen_GB.UTF-8)ため、ロケール(またはGNUシステムではmy )で行われます。と比較してください。以外のロケールでは、ソート順は通常、バイト値に基づいていません/s9printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sortprintf '/proc/%s/status\n' 1 1992 | LC_ALL=C sortC
ステファンChazelas

@StephaneChazelasいい点ですが、ロケールについてはそうではありませんでした。ここでも、自由に編集して精度を追加し、クレジットを自分のものにします(少なくとも履歴編集では)。
Tensibai

2
できました。この回答は、ここで最も投票された回答よりもはるかに優れています。それはより多くの賛成に値します。それとここでの他の答えは、なぜテキストを処理するためにシェルループを使用することが悪い習慣と考えられるのかで議論されました これが私をここに連れてきたものです。
Stephane Chazelas

6

さらに2つのバリエーション:

そのためtopか、htop閲覧、小規模システムにインストールされていないことができ/proc、常に可能なご滞在を。

小さなシステムでも、shell...

バリアント!(bashのみではありません)

これはlolotuxスクリプトとまったく同じですがgrepawkやへの分岐がありませんps。これはずっと速いです!

そして 最貧国の一つです パフォーマンスに関しては、このスクリプトが適切に実行されるように少し作業が行われました と他のいくつか。その後、(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のコメントを参照してください。

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

プロセス名にスペース、タブ:、、バックスラッシュ、ワイルドカード、または制御文字が含まれていないことを前提としています。
Stephane Chazelas 16

@StephaneChazelasありがとう!私が追加した[1-9]*(なしのみの番号のパスをカウントするためself、またthread-self
F. HAURI

1
構文はわかっていますが、プロセス名はわかっていません。少なくとも変数を引用してください。(いずれにしても、あなたのスクリプトはloloxuxよりもずっと悪いわけではありません)。
Stephane Chazelas 16

1
Linuxのプロセス名には0以外の任意のバイト値を含めることができますが、長さは15バイトに制限されています。の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、変数を引用するのを忘れた場合などのようなことで実行できる損害は限られます。
Stephane Chazelas 16

1
これ(少なくとも私が試したperlバージョン)は、他の回答よりも非常に高速です。
David Gardner

5

私はこの長いワンライナーにウェブ上の別のスクリプトを採用しました:

 { 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、スワップ量の2つの列にあります。上記のバージョンではtr、非数値コンポーネントが削除されます。どちらの場合も、出力はpidで数値順にソートされます。


2
これは良いことですが、最初のものはpidの昇順でソートします(sort -n)。より良い使用法は、スワップ使用法で降順にソートすることです(リストの前で最も使用されます)。それを取得するには、「sort -n」を「sort -n -k 3 -r」に変更します
Stan Brajewski

3

MacOSXでは、topコマンドも実行しますが、「o」、「vsize」、Enterキーの順に入力する必要があります。


2

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

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



1

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

また、htopなどの優れたツールを使用して、どのプロセスが多くのメモリを使用しているか、全体でどのくらいのスワップが使用されているかを確認します。


1

iotop非常に便利なツールです。プロセス/スレッドごとのI / Oとスワップの使用状況のライブ統計を提供します。デフォルトではスレッドごとに表示されますが、iotop -Pプロセスごとの情報を取得することができます。これはデフォルトでは使用できません。rpm / apt経由でインストールする必要がある場合があります。


1

これは、@ 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

1

2015年のカーネルパッチSwapPsshttps://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、2番目の列はKiBでのスワップの使用法で、行の残りの部分は実行中のコマンドです。同一のスワップカウントは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、最後に追加してください。他の可能な診断も失う可能性があることに注意してください。

実際の例では、これにより、1台のサーバーで実行されている各apache子の最大40 MBのスワップ使用量を報告する他のツールが、実際に子ごとに使用される7〜3630 KBの実際の使用量に変更されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.