在Linux下,如何发现哪个进程使用交换空间更多?


当前回答

另一种在shell中避免循环的脚本变体:

#!/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对输出进行排序。

我希望我已经对代码进行了足够的注释,以说明它的功能。

其他回答

与@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

不完全清楚您的意思是要找到交换出最多页的进程还是导致交换出最多页的进程。

对于前者,您可以运行top并按swap排序(按'Op'),对于后者,您可以运行vmstat并查找'so'的非零条目。

这是我的一句话:

cat /proc/*/status | grep -E 'VmSwap:|Name:' | grep VmSwap -B1 | cut -d':' -f2 | grep -v '\-\-' | grep -o -E '[a-zA-Z0-9]+.*$' | cut -d' ' -f1 | xargs -n2 echo | sort -k2 -n

这一行的步骤是:

Get all the data in /proc/process/status for all processes Select the fields VmSwap and Name for each Remove the processes that don't have the VmSwap field Remove the names of the fields (VmSwap: and Name:) Remove lines with -- that were added by the previous step Remove the spaces at the start of the lines Remove the second part of each process name and " kB" after the swap usage number Take name and number (process name and swap usage) and put them in one line, one after the other Sort the lines by the swap usage

运行top,然后按OpEnter。现在进程应该根据它们的交换使用情况进行排序。

这是一个更新,因为我原来的答案没有提供一个确切的答案,在评论中指出的问题。从htop常见问题:

It is not possible to get the exact size of used swap space of a process. Top fakes this information by making SWAP = VIRT - RES, but that is not a good metric, because other stuff such as video memory counts on VIRT as well (for example: top says my X process is using 81M of swap, but it also reports my system as a whole is using only 2M of swap. Therefore, I will not add a similar Swap column to htop because I don't know a reliable way to get this information (actually, I don't think it's possible to get an exact number, because of shared pages).

我在网上改编了一个不同的脚本来写这句长单句:

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

这个版本的输出有两列:pid,交换量。在上面的版本中,tr删除非数值组件。在这两种情况下,输出都是按照pid数值排序的。