今回はプロセス毎のswap sizeを確認する方法のお話です。
muninでMemory usageグラフを眺めていて、swap sizeが数100MB程度発生していて、どのプロセスがどの程度swappingしているのか知りたくなりました。
そこでprocファイルシステムに何か情報があるのかと調べてみたら、/proc/ [ PID ] /statusで欲しい情報が確認出来そうです。以下のコマンド結果はmysqldプロセスの情報です。
# cat /proc/1263/status
Name: mysqld
State: S (sleeping)
Tgid: 1263
Pid: 1263
PPid: 1161
TracerPid: 0
Uid: 27 27 27 27
Gid: 27 27 27 27
Utrace: 0
FDSize: 256
Groups: 27
VmPeak: 1234116 kB
VmSize: 1195492 kB
VmLck: 0 kB
VmHWM: 29500 kB
VmRSS: 18952 kB
VmData: 1135196 kB
VmStk: 88 kB
VmExe: 6532 kB
VmLib: 7376 kB
VmPTE: 436 kB
VmSwap: 23000 kB
Threads: 13
SigQ: 0/7817
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000087007
SigIgn: 0000000000001006
SigCgt: 00000001800066e9
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed: 3
Cpus_allowed_list: 0-1
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 233669
nonvoluntary_ctxt_switches: 29
/proc/ [ PID ] /statusのVmSwapという項目がswap sizeだということが判明しました。このswap sizeの大きい順に表示するには以下コマンドで表示できました。
# grep VmSwap /proc/*/status | sort -k 2 -r | head
/proc/1416/status:VmSwap: 764 kB
/proc/1425/status:VmSwap: 632 kB
/proc/1171/status:VmSwap: 356 kB
/proc/525/status:VmSwap: 280 kB
/proc/1479/status:VmSwap: 280 kB
/proc/1448/status:VmSwap: 252 kB
/proc/1478/status:VmSwap: 248 kB
/proc/1262/status:VmSwap: 248 kB
/proc/1263/status:VmSwap: 212 kB
/proc/1440/status:VmSwap: 144 kB
上記したとおり、procファイルシステムを利用してプロセスごとのswap sizeを表示できるのですが、残念ながらこれではプロセス名が分からず不便です。幸い、この/proc/ [ PID ] /statusファイルにはNameという項目でプロセス名があるので、swap sizeの大きいPID順にプロセス名も取得し、swap sizeの大きいプロセス順に表示するperlスクリプトを書きました。
#!/bin/env perl
# pachi
#
# This script find out process currently swapped by /proc/$PID/status
use strict;
use warnings;
# When you want to debug, you should exec "export SCRIPT_DEBUG=1".
my $debug = $ENV{SCRIPT_DEBUG} ? 1 : 0;
my $proc_status = `grep VmSwap /proc/*/status | sort -k 2 -r`;
my @proc_status = split m{\n}, $proc_status;
my $proc_swaps = [];
foreach my $status_line ( @proc_status ) {
my $process_info = {};
chomp $status_line;
my @status_line = split /\s+/, $status_line;
my $proc_path = $status_line[0];
my $proc_swap_value = $status_line[1];
my $pid = ( split( /\//,$proc_path ) )[2];
if ( ! -f "/proc/$pid/status" ) {
# file not found! next.
next;
}
# get process name by pid
my $process_name_line = `grep Name /proc/$pid/status`;
chomp $process_name_line;
my @process_name_line = split /\s+/, $process_name_line;
my $process_name = $process_name_line[1];
$process_info->{name} = $process_name;
$process_info->{pid} = $pid;
$process_info->{swap_value} = $proc_swap_value;
# Process information is stored in hash
push @$proc_swaps ,$process_info;
}
# Print header
printf "--------------------+----------+---------------+\n";
printf " Swap size classified by processes |\n";
printf "--------------------+----------+---------------+\n";
printf " Process Name | PID | Swap Size |\n";
printf "--------------------+----------+---------------+\n";
# Print every process info
foreach my $proc_swap ( @$proc_swaps ) {
printf ("%-20s|", "$proc_swap->{name}");
printf ("%10s |", "$proc_swap->{pid}");
printf ("%15s |", "$proc_swap->{swap_value}KB");
printf "\n";
}
# Print footer
printf "\n";
exit 0;
"grep VmSwap"しているのでswap sizeに特化しているんですけど、以下がスクリプトを実行した感じです。実行結果はプロセス名とPIDとswap sizeをprintfで整形して出力しています。
$ ./swaplist.pl | head -20
--------------------+----------+---------------+
Swap size classified by processes |
--------------------+----------+---------------+
Process Name | PID | Swap Size |
--------------------+----------+---------------+
ruby | 7640| 70724KB|
ruby | 28861| 29220KB|
ruby | 10300| 28820KB|
httpd | 25049| 27496KB|
mysqld | 1263| 25092KB|
httpd | 24997| 11612KB|
ruby | 24983| 6412KB|
rsyslogd | 1064| 6368KB|
munin-node | 8543| 5500KB|
httpd | 25051| 5276KB|
httpd | 24994| 4304KB|
httpd | 28182| 3988KB|
httpd | 24976| 3932KB|
httpd | 25000| 3928KB|
httpd | 25024| 3856KB|
実行環境ではRailsアプリケーションを動かしています。そして、実行結果から、ruby、httpd、mysqldなどのプロセスがswappingしていることが分かりました!!
Perl |
3
|
Linux |
16
|
Jenkins |
1
|
CI |
1
|
Bashシェル |
1
|
シェルスクリプト |
1
|
Munin |
7
|
Ruby on Rails |
7
|
plenv |
1
|
sudo |
2
|
Cobbler |
6
|
ruby |
1
|
rbenv |
1
|
WeeChat |
1
|
tmux |
2
|
Webistrano |
1
|
capistrano |
1
|
puppet |
8
|
growthforecast |
1
|
Supervisor |
1
|
perlbrew |
1
|
git |
2
|
Python |
1
|
pip |
1
|
PHP |
1
|
Nginx |
1
|
MySQL |
2
|
LXC |
2
|
RPM |
3
|
ImageMagick |
1
|
Subversion |
1
|
qmail |
3
|
yum |
1
|
ucspi-tcp |
1
|
daemontools |
1
|
Puppet |
1
|
IPVS |
1
|
Kickstart |
1
|
aaa |
0
|