だから、私はスワップ使用率が高いシステムでスワップ使用がどこから来るのかについていくつかの調査をしようとしています:
# free
total used free shared buffers cached
Mem: 515324 508800 6524 0 4852 27576
-/+ buffers/cache: 476372 38952
Swap: 983032 503328 479704
プロセスごとに使用されるスワップを合計する:
# for proc in /proc/*; do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe`'"}'; done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'
0 /bin/gawk
0 /bin/sort
0 /usr/bin/readlink
28 /sbin/xxxxxxxx
52 /sbin/mingetty
52 /sbin/mingetty
52 /sbin/mingetty
52 /sbin/mingetty
56 /sbin/mingetty
56 /sbin/mingetty
60 /xxxxxxxxxxx
60 /usr/sbin/xxx
84 /usr/sbin/xxx
108 /usr/bin/xxx
168 /bin/bash
220 /sbin/init
256 /sbin/rsyslogd
352 /bin/bash
356 /bin/bash
360 /usr/sbin/sshd
496 /usr/sbin/crond
672 /usr/sbin/sshd
12972 /opt/jdk1.6.0_22/bin/Java
80392 /usr/libexec/mysqld
311876 /opt/jdk1.6.0_22/bin/Java
408780 Total
合計使用済みスワップの値が低くなります。残りの使用済みスワップスペースはどこにありますか?カーネル内のvmalloc()されたメモリですか?他に何か?どうすればそれを識別できますか?
Meminfoの出力:
# cat /proc/meminfo
MemTotal: 515324 kB
MemFree: 6696 kB
Buffers: 5084 kB
Cached: 28056 kB
SwapCached: 157512 kB
Active: 429372 kB
Inactive: 65068 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 515324 kB
LowFree: 6696 kB
SwapTotal: 983032 kB
SwapFree: 478712 kB
Dirty: 100 kB
Writeback: 0 kB
AnonPages: 399456 kB
Mapped: 8792 kB
Slab: 7744 kB
PageTables: 1820 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 1240692 kB
Committed_AS: 1743904 kB
VmallocTotal: 507896 kB
VmallocUsed: 3088 kB
VmallocChunk: 504288 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 4096 kB
観察している違いは、実際にはスワップスペースが考慮されていないためではありません。カーネルが/proc/*/exe
リンクに追加することがある「(削除済み)」は、readlink
によって出力され、awkスクリプトで解析エラーを引き起こしており、バイナリが全体に存在しないプロセスを数えていません。
一部のカーネルは、プロセスの元の実行可能ファイルが存在しなくなったときに、「[削除済み]」という単語を/proc/*/exe
symlinkターゲットに追加します。
コマンドが合計より少ないことを示している理由は、これが原因です。そのようなリンクでのreadlink
の出力は、「/ path/to/bin(deleted)」のようなものになります。これにより、出力が文字列に戻されると、awk
で解析エラーが発生します(括弧とスペースは好きではありません)。 。たとえば、次のようにします。
for a in /proc/*/exe ; do readlink $a ; done | grep deleted
そして、「(削除済み)」が追加されたエントリがいくつか表示されます。これらのエントリのスワップ使用量を見ると、結果のawk
エラーが原因で合計が計算され、最終的な合計に含まれないため、それらの合計は表示される不一致と一致します。
Stderrをどこにもリダイレクトせずに元のコマンドを実行すると、おそらくいくつかの「暴走文字列定数」エラーに気付くでしょう。これらのエラーは上記の結果であり、無視してはなりません。
元のコマンドに対するその他の潜在的な改善を無視して、次のように「(削除済み)」を削除することで変更できます(readlink
の出力に|awk '{print $1}'
が追加されていることに注意してください):
for proc in /proc/*; \
do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe|awk '{print $1}' `'" }'; \
done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'
名前にスペースが含まれている場合、awk
の出力を修正するためのreadlink
の使用は失敗する可能性があります-sed
または任意の方法を使用できます。
ボーナス情報
ちなみに、smem -t
を使用することもできます。 「スワップ」列には、必要なものが表示されます。
ただし、自分で計算する場合は、/proc/*/status
のVmSwap
フィールドからこの情報を直接取得することもできます(smapsはカーネルサポートを必要とし、常に利用できるとは限りません)。最初にエラーを回避する適切なファイル名パターン:
for proc in /proc/[0-9]*; do \
awk '/VmSwap/ { print $2 "\t'`readlink $proc/exe | awk '{ print $1 }'`'" }' $proc/status; \
done | sort -n | awk '{ total += $1 ; print $0 } END { print total "\tTotal" }'
実際のバイナリが不要で、プロセス名のみを処理できる場合は、status
からeverythingを取得できます。
for a in /proc/*/status ; do \
awk '/VmSwap|Name/ { printf $2 " " } END { print "" }' $a ; \
done | awk '{ total+=$2 ; print $0 } END { print "Total " total }'
そして最後に、PIDだけで十分であれば、awk
を使用してすべてを実行できます。
awk '/VmSwap/ { total += $2; print $2 "\t" FILENAME } END { print total "\tTotal" }' /proc/*/status
注:
これは、free
とsmem
の間に違いがないと言っているのではありません(後者はスクリプトと同じです)。たくさんあります(たとえば、 https://www.google.com/search?q=smem+free を参照してください)。これは、最初のページに、メモリに関する質問に答えるのに十分な結果があります使用法)。しかし、適切なテストがないと、特定の状況に対処できません。
スワップは、カーネルがより多くの空きRAMを必要とする場合、または単にそれがしばらく使用されていないためにtmpfsによっても使用されます。そのため、tmpfsを使用するとスワップが消費される可能性があります。