ภายใต้ Linux ฉันจะรู้ได้อย่างไรว่ากระบวนการใดที่ใช้พื้นที่สว็อปมากขึ้น?
ภายใต้ Linux ฉันจะรู้ได้อย่างไรว่ากระบวนการใดที่ใช้พื้นที่สว็อปมากขึ้น?
คำตอบ:
เรียกใช้ด้านบนOpEnterแล้วกด ตอนนี้กระบวนการควรเรียงลำดับตามการใช้ swap ของพวกเขา
นี่คือการอัปเดตเนื่องจากคำตอบดั้งเดิมของฉันไม่ได้ให้คำตอบที่ถูกต้องสำหรับปัญหาตามที่ระบุไว้ในความคิดเห็น จากคำถามที่พบบ่อย htop :
เป็นไปไม่ได้ที่จะได้ขนาดที่แน่นอนของพื้นที่สว็อปที่ใช้แล้วของกระบวนการ ปลอมข้อมูลนี้ด้วยการทำ SWAP = VIRT - RES แต่นั่นไม่ใช่ตัวชี้วัดที่ดีเพราะสิ่งอื่น ๆ เช่นหน่วยความจำวิดีโอนับเป็น VIRT เช่นกัน (ตัวอย่าง: top บอกว่ากระบวนการ X ของฉันใช้ 81M ของการแลกเปลี่ยน แต่ก็ยัง รายงานว่าระบบของฉันโดยรวมกำลังใช้การสลับเพียง 2M ดังนั้นฉันจะไม่เพิ่มคอลัมน์สลับที่คล้ายกันไปที่ htop เพราะฉันไม่ทราบวิธีที่เชื่อถือได้ในการรับข้อมูลนี้ (จริง ๆ แล้วฉันไม่คิดว่าจะเป็นไปได้ จำนวนที่แน่นอนเนื่องจากเพจที่ใช้ร่วมกัน)
สคริปต์ที่ดีที่สุดที่ฉันพบคือในหน้านี้: http://northernmost.org/blog/find-out-what-is-using-your-swap/
นี่คือตัวแปรหนึ่งของสคริปต์และไม่จำเป็นต้องรูท:
#!/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"
Overall swap used: 260672 KB
ในขณะที่การแสดงฟรี738932
ที่ใช้ ...
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
สำหรับ Debian / RH 6x +, Arch, Ubuntu (RH 5x มีVmSize
) ( แหล่งที่มา ) เช่นเดียวกับ @dgunchev มันจะให้การแลกเปลี่ยนโดยรวมน้อยกว่าfree
มาก @Tensibai ไม่ทำงานบน Arch; awk ของคุณอาจขาดอะไรบางอย่าง
top
: northernmost.org/blog/swap-usage-5-years-later
นี่คืออีกหนึ่งตัวแปรของสคริปต์ แต่มีจุดประสงค์ที่จะให้ผลลัพธ์ที่อ่านได้มากขึ้น (คุณต้องเรียกใช้สิ่งนี้เป็นรูทเพื่อรับผลลัพธ์ที่แน่นอน):
#!/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}/";
args
แทนcomm
ในps
คำสั่งตั้งแต่ฉันมีจำนวนมากของกระบวนการที่มีชื่อเดียวกัน แต่ข้อโต้แย้งที่แตกต่างกัน (พวงของกระบวนการหลาม gunicorn ก) เช่น:ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
สามารถทำให้ง่ายขึ้นเป็นawk ' /VmSwap/ { print $2 }'
ฉันสังเกตเห็นว่าเธรดนี้ค่อนข้างเก่า แต่ถ้าคุณบังเอิญสะดุดกับมันอย่างที่ฉันทำไปแล้วคำตอบอื่นคือ: ใช้ smem
นี่คือลิงค์ที่จะบอกคุณทั้งสองวิธีการติดตั้งและวิธีการใช้งาน:
http://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
ยังไม่ชัดเจนนักถ้าคุณหมายถึงคุณต้องการค้นหากระบวนการที่มีการสลับหน้าเว็บเป็นส่วนใหญ่หรือกระบวนการที่ทำให้หน้าส่วนใหญ่สลับไปมา
สำหรับครั้งแรกที่คุณสามารถเรียกใช้top
และสั่งซื้อโดยสลับ (กด 'Op') สำหรับหลังคุณสามารถเรียกใช้vmstat
และมองหารายการที่ไม่เป็นศูนย์สำหรับ 'ดังนั้น'
คำสั่งด้านบนยังมีฟิลด์เพื่อแสดงจำนวนความผิดพลาดของหน้าสำหรับกระบวนการ กระบวนการที่มีความผิดพลาดสูงสุดที่หน้าจะเป็นกระบวนการที่มีการแลกเปลี่ยนมากที่สุด สำหรับ daemons ที่รันมานานอาจเป็นเพราะพวกเขามีข้อบกพร่องของหน้าจำนวนมากในตอนเริ่มต้นและจำนวนจะไม่เพิ่มขึ้นในภายหลัง ดังนั้นเราต้องสังเกตว่าข้อบกพร่องของหน้านั้นเพิ่มขึ้นหรือไม่
ตัวแปรสคริปต์อื่นที่หลีกเลี่ยงการวนซ้ำในเชลล์:
#!/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
ฉันหวังว่าฉันจะแสดงความคิดเห็นรหัสเพียงพอที่จะบอกว่ามันทำอะไร
bash
ขยายไดเรกทอรีในวิธีการเรียงลำดับ (คำศัพท์ไม่ใช่ตัวเลข) ลำดับแบบสุ่มจะลดลงไปตามวิธีการจัดawk
เก็บอาร์เรย์ (ตารางแฮช) และวิธีfor p in pname
ดึงข้อมูล
/proc/1/status
มาหลังจากนั้น/proc/1992/status
และ/
มีรหัส ASCII ด้านบนรหัส 9 ASCII นี้ให้รูปลักษณ์ "ความรู้สึกแบบสุ่ม" ฉันเห็นด้วยกับตารางแฮช awk ฉันเอาช็อตคัตที่นี่อย่าลังเลที่จะแก้ไขคำตอบเพื่อให้มีการระบุแหล่งที่มาในประวัติการแก้ไข
/proc/1/status
จะไม่มา/proc/1992/status
ในโลแคล C ซึ่งคำสั่งนั้นอ้างอิงตามค่าไบต์ มันทำในสถานที่ของคุณ (หรือในen_GB.UTF-8
ระบบ GNU ของฉัน) เพราะ/
มีการละเว้นในตัวอย่างแรกในอัลกอริทึมการเรียง (และs
เรียงลำดับหลัง9
) เปรียบเทียบกับprintf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
ในโลแคลอื่นนอกเหนือจากC
นั้นการเรียงลำดับโดยทั่วไปจะไม่ขึ้นอยู่กับค่าไบต์
เนื่องจากtop
หรือhtop
อาจไม่ได้ติดตั้งในระบบขนาดเล็กการเรียกดู/proc
จึงเป็นไปได้เสมอ
แม้ในระบบขนาดเล็กคุณจะพบshell
...
ตรงนี้เป็นสิ่งเดียวกันกว่าสคริปต์ lolotuxแต่ไม่มีส้อมใด ๆ เพื่อgrep
, หรือawk
ps
นี่คือเร็วมาก!
และเป็น ทุบตี เป็นหนึ่งในคนที่ยากจนที่สุด เปลือก เกี่ยวกับประสิทธิภาพมีการทำงานเล็กน้อยเพื่อให้มั่นใจว่าสคริปต์นี้จะทำงานได้ดี ชน, busyboxและอื่น ๆ จากนั้น ( ขอบคุณ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
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é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
:
แบ็กสแลชไวด์การ์ดหรืออักขระควบคุม
[1-9]
ก่อนแล้ว*
สำหรับการนับเส้นทางที่มีหมายเลขเท่านั้น (ไม่ใช่self
, หรือthread-self
)
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
มี จำกัด เมื่อคุณลืมอ้างอิงตัวแปรของคุณ
ฉันปรับสคริปต์อื่นบนเว็บให้เป็นหนึ่งซับในแบบยาว:
{ 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, จำนวน swap ในเวอร์ชันด้านบนจะตัดtr
ส่วนประกอบที่ไม่ใช่ตัวเลข ในทั้งสองกรณีผลลัพธ์จะถูกจัดเรียงตัวเลขโดย pid
บน MacOSX คุณเรียกใช้คำสั่งด้านบนเช่นกัน แต่ต้องพิมพ์ "o" แล้ว "vsize" แล้วกด ENTER
ฉันคิดว่าคุณสามารถเดาได้ดีจากการรันtop
และค้นหากระบวนการที่ใช้งานอยู่โดยใช้หน่วยความจำจำนวนมาก การทำแบบนี้เป็นเรื่องยาก - เพียงแค่ดูการอภิปรายที่ไม่รู้จบเกี่ยวกับการวิเคราะห์พฤติกรรมของ Linux OOM
การสลับเป็นฟังก์ชั่นที่มีหน่วยความจำในการใช้งานมากกว่าการติดตั้งดังนั้นจึงมักจะตำหนิได้ยากในกระบวนการเดียว หากเป็นปัญหาต่อเนื่องทางออกที่ดีที่สุดคือการติดตั้งหน่วยความจำเพิ่มเติมหรือทำการเปลี่ยนแปลงระบบอื่น ๆ
ให้ผลรวมและเปอร์เซ็นต์สำหรับกระบวนการโดยใช้การแลกเปลี่ยน
smem -t -p
ที่มา: https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
ผมไม่ทราบว่าของคำตอบโดยตรงใด ๆ ที่เป็นวิธีการที่จะค้นหาสิ่งที่ขั้นตอนการใช้พื้นที่ swap แต่การเชื่อมโยงนี้อาจจะเป็นประโยชน์ อีกอันที่ดีอยู่ตรงนี้
นอกจากนี้ให้ใช้เครื่องมือที่ดีเช่น htop เพื่อดูว่ากระบวนการใดที่ใช้หน่วยความจำจำนวนมากและใช้การแลกเปลี่ยนโดยรวมเท่าไร
iotop
เป็นเครื่องมือที่มีประโยชน์มาก มันให้สถิติสดของ I / O และการใช้งานการแลกเปลี่ยนต่อกระบวนการ / ด้าย โดยค่าเริ่มต้นจะแสดงต่อเธรด แต่คุณสามารถทำได้iotop -P
เพื่อรับข้อมูลต่อกระบวนการ ไม่สามารถใช้งานได้ตามค่าเริ่มต้น คุณอาจต้องติดตั้งผ่าน rpm / apt
นี่คือเวอร์ชันที่ให้ผลลัพธ์เหมือนกับสคริปต์โดย @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
ตั้งแต่ปี 2558 เคอร์เนลแพตช์ที่เพิ่มSwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ) ในที่สุดก็สามารถได้รับการนับการแลกเปลี่ยนตามสัดส่วนซึ่งหมายความว่าหากกระบวนการมีการสลับเป็นจำนวนมากและจากนั้นจะดำเนินการทั้งกระบวนการแยก จะมีการรายงานการแลกเปลี่ยน 50% ต่อครั้ง และถ้าอย่างใดอย่างหนึ่งแล้วส้อมแต่ละกระบวนการจะถูกนับ 33% ของหน้าสลับเปลี่ยนดังนั้นหากคุณนับการแลกเปลี่ยน swap เหล่านั้นทั้งหมดเข้าด้วยกันคุณจะได้รับการใช้งานแลกเปลี่ยนจริงแทนที่จะเป็นมูลค่าคูณด้วยจำนวนกระบวนการ
ในระยะสั้น:
(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 คอลัมน์ที่สองคือการใช้ swap ใน KiB และส่วนที่เหลือของบรรทัดคือคำสั่งที่ถูกเรียกใช้งาน จำนวน swap ที่เหมือนกันจะถูกจัดเรียงตาม 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
ไปยังจุดสิ้นสุด โปรดทราบว่าคุณอาจสูญเสียการวินิจฉัยที่เป็นไปได้อื่น ๆ เช่นกัน
ในกรณีตัวอย่างในโลกแห่งความจริงสิ่งนี้จะเปลี่ยนเครื่องมืออื่น ๆ ที่รายงานการใช้ swap ~ 40 MB สำหรับเด็ก apache แต่ละคนที่ทำงานบนเซิร์ฟเวอร์หนึ่งเครื่องเป็นการใช้งานจริงระหว่าง 7-3630 KB ที่ใช้จริงต่อเด็กหนึ่งคน