263

Linux では、どのプロセスがスワップ領域をより多く使用しているかを調べるにはどうすればよいですか?

4

19 に答える 19

313

私が見つけた最高のスクリプトはこのページにあります: 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"
于 2011-08-24T17:58:15.467 に答える
110

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

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

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

于 2009-01-26T14:47:05.150 に答える
57

これはスクリプトの別の変形ですが、より読みやすい出力を提供することを目的としています (正確な結果を得るには、これをルートとして実行する必要があります)。

#!/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}/";
于 2012-09-03T22:24:27.737 に答える
10

ほとんどのページをスワップアウトしたプロセスを見つけたいのか、ほとんどのページをスワップアウトさせたプロセスを見つけたいのかは、完全には明確ではありません。

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

于 2009-01-26T14:54:09.787 に答える
9

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

#!/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方法まで) でプログラムごとの使用法を取得するか、出力を pid でソートすることです。awkscript.sh 1

コードが何をするかを説明するのに十分なコメントをしたことを願っています。

于 2015-09-01T09:10:45.780 に答える
7

さらに 2 つのバリアントがあります。

小規模なシステムにはインストールできなかっtopたりするため、ブラウジングは常に可能です。htop/proc

小規模なシステムでも、shell...

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

これはlolotux スクリプトgrepとまったく同じですが、 、awkまたはへのフォークはありませんps。これはずっと速いです!

また、はパフォーマンスに関して最も貧弱ななどの下で適切に実行されるように、少し作業が行われました。その後、( Stéphane Chazelas のおかげで) 再びずっと速くなりました!

#!/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
for FILE in /proc/[0-9]*/status ;do
    SUM=0
    while read FIELD VALUE;do
        case $FIELD in
            Pid )    PID=$VALUE         ;;
            Name )   PROGNAME="$VALUE"  ;;
            VmSwap ) SUM=${VALUE%% *} ; break ;;
        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éphane Chazelas のコメントを参照してください。

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
于 2016-08-05T13:24:48.527 に答える
6

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

于 2012-07-27T07:31:15.973 に答える
3

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

于 2012-01-19T09:31:52.883 に答える
3

追加する 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、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 の実際の使用量に変更されます。

于 2020-05-08T09:11:00.510 に答える
2

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

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

于 2009-01-26T14:38:55.917 に答える
1

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

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

于 2009-01-26T14:40:43.697 に答える
0

@lolotuxと同じ答えですが、ソートされた出力があります:

printf 'Computing swap usage...\n';
swap_usages="$(
    SUM=0
    OVERALL=0

    for DIR in `find /proc/ -maxdepth 1 -type d -regex "^/proc/[0-9]+"`
    do
        PID="$(printf '%s' "$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
            printf "$SUM KB ($PROGNAME) swapped PID=$PID\\n"
        fi
        let OVERALL=$OVERALL+$SUM
        SUM=0
        break
    done
    printf '9999999999 Overall swap used: %s KB\n' "$OVERALL"
)"

printf '%s' "$swap_usages" | sort -nk1

出力例:

Computing swap usage...
2064 KB (systemd) swapped PID=1
59620 KB (xfdesktop) swapped PID=21405
64484 KB (nemo) swapped PID=763627
66740 KB (teamviewerd) swapped PID=1618
68244 KB (flameshot) swapped PID=84209
763136 KB (plugin_host) swapped PID=1881345
1412480 KB (java) swapped PID=43402
3864548 KB (sublime_text) swapped PID=1881327
9999999999 Overall swap used: 2064 KB
于 2020-11-16T11:17:57.417 に答える