Trong Linux, làm cách nào để biết quy trình nào đang sử dụng không gian hoán đổi nhiều hơn?
Trong Linux, làm cách nào để biết quy trình nào đang sử dụng không gian hoán đổi nhiều hơn?
Câu trả lời:
Chạy lên trên rồi nhấn OpEnter. Bây giờ các quy trình nên được sắp xếp theo cách sử dụng trao đổi của họ.
Đây là một bản cập nhật vì câu trả lời ban đầu của tôi không cung cấp câu trả lời chính xác cho vấn đề như được nêu trong các bình luận. Từ câu hỏi thường gặp :
Không thể có được kích thước chính xác của không gian hoán đổi được sử dụng của một quy trình. Top giả mạo thông tin này bằng cách tạo SWAP = VIRT - RES, nhưng đó không phải là một số liệu tốt, bởi vì những thứ khác như bộ nhớ video cũng được tính trên VIRT (ví dụ: top nói rằng quá trình X của tôi đang sử dụng 81M trao đổi, nhưng nó cũng báo cáo toàn bộ hệ thống của tôi chỉ sử dụng 2 triệu trao đổi. Do đó, tôi sẽ không thêm một cột Hoán đổi tương tự vào htop vì tôi không biết một cách đáng tin cậy để có được thông tin này (thực sự, tôi không nghĩ có thể lấy được một con số chính xác, vì các trang được chia sẻ).
Kịch bản tốt nhất tôi tìm thấy là trên trang này: http : // nắc Maximum.org/blog/find-out-what-is-USE-your-swap/
Đây là một biến thể của tập lệnh và không cần 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"
Overall swap used: 260672 KB
, trong khi các chương trình miễn phí 738932
được sử dụng ...
for file in /proc/*/status ; do awk '/Tgid|VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | grep kB | sort -k 3 -n
đối với Debian / RH 6x +, Arch, Ubuntu (RH 5x có VmSize
) ( nguồn ). Giống như @dgunchev, nó cung cấp tổng số trao đổi ít hơn nhiều so với free
. @Tensibai không hoạt động trên Arch; awk của bạn có thể thiếu một cái gì đó.
top
: northernmost.org/blog/swap-usage-5-years-later
Đây là một biến thể khác của tập lệnh, nhưng có nghĩa là cho đầu ra dễ đọc hơn (bạn cần chạy nó dưới dạng root để có kết quả chính xác):
#!/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
thay vì comm
trong ps
lệnh vì tôi có rất nhiều quy trình có cùng tên nhưng các đối số khác nhau (một loạt các quy trình gunicorn python). Tức là:ps -p $PID -o args --no-headers
grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'
có thể được đơn giản hóa làawk ' /VmSwap/ { print $2 }'
Tôi đã nhận thấy chủ đề này khá cũ, nhưng nếu bạn tình cờ vấp phải nó, như tôi vừa làm, một câu trả lời khác là: sử dụng smem.
Đây là một liên kết cho bạn biết cả cách cài đặt và cách sử dụng nó:
http://www.cyberciti.biz/faq/linux-which- Process-is-USE-swap /
Điều đó không hoàn toàn rõ ràng nếu bạn muốn nói rằng bạn muốn tìm ra quy trình có hầu hết các trang bị tráo đổi hoặc quá trình khiến hầu hết các trang bị tráo đổi.
Đối với người đầu tiên bạn có thể chạy top
và đặt hàng bằng cách trao đổi (nhấn 'Op'), đối với lần đầu tiên , bạn có thể chạy vmstat
và tìm kiếm các mục nhập khác không cho 'so'.
Lệnh trên cùng cũng chứa một trường để hiển thị số lỗi trang cho một quy trình. Quá trình có lỗi trang tối đa sẽ là quá trình hoán đổi nhiều nhất. Đối với các trình tiện ích chạy dài, có thể chúng phải chịu một số lượng lớn lỗi trang ở đầu và số lượng không tăng sau đó. Vì vậy, chúng ta cần phải quan sát xem các lỗi trang đang gia tăng.
Một biến thể script khác tránh vòng lặp trong 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
}'
Sử dụng tiêu chuẩn là script.sh
để có được mức sử dụng cho mỗi chương trình với thứ tự ngẫu nhiên (giảm đến cách awk
lưu trữ băm của nó) hoặc script.sh 1
sắp xếp đầu ra theo pid.
Tôi hy vọng tôi đã nhận xét mã đủ để nói những gì nó làm.
bash
mở rộng các thư mục theo cách được sắp xếp (từ vựng, không phải bằng số). Thứ tự ngẫu nhiên là cách awk
lưu trữ các mảng của nó (bảng băm) và cách for p in pname
lấy chúng.
/proc/1/status
xuất hiện sau /proc/1992/status
đó và /
có mã ascii bên trên mã 9 ascii. , Tôi đã chọn một phím tắt ở đây. Vui lòng chỉnh sửa câu trả lời để giữ sự ghi nhận trong lịch sử chỉnh sửa.
/proc/1/status
sẽ không đến sau /proc/1992/status
trong miền địa phương C nơi thứ tự dựa trên giá trị byte. Nó thực hiện trong miền địa phương của bạn (hoặc trong en_GB.UTF-8
hệ thống GNU của tôi ), vì /
đã bị bỏ qua trong trường hợp đầu tiên trong thuật toán đối chiếu (và s
sắp xếp sau 9
). So sánh printf '/proc/%s/status\n' 1 1992 | LC_ALL=en_GB.UTF-8 sort
với printf '/proc/%s/status\n' 1 1992 | LC_ALL=C sort
. Ở các địa phương khác C
, thứ tự sắp xếp thường không dựa trên giá trị byte.
Bởi vì top
hoặc htop
không thể được cài đặt trên các hệ thống nhỏ, việc duyệt /proc
vẫn luôn khả thi.
Ngay cả trên các hệ thống nhỏ, bạn sẽ tìm thấy một shell
...
Điều này hoàn toàn giống với tập lệnh lolotux , nhưng không có bất kỳ ngã ba nào grep
, awk
hoặc ps
. Điều này nhanh hơn rất nhiều!
Và như bash là một trong những người nghèo nhất vỏ liên quan đến hiệu suất, một công việc nhỏ đã được thực hiện để đảm bảo tập lệnh này sẽ chạy tốt dấu gạch ngang, bận rộnvà một số khác. Sau đó, ( nhờ Stéphane Chazelas ,) trở nên nhanh hơn rất nhiều lần nữa!
#!/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
Đừng quên trích dẫn gấp đôi "$PROGNAME"
! Xem bình luận của Stéphane Chazelas :
read FIELD PROGNAME < <(
perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
)
echo $FIELD "$PROGNAME"
Đừng thử echo $PROGNAME
mà không có trích dẫn kép trên hệ thống hợp lý và sẵn sàng tiêu diệt lớp vỏ hiện tại trước đó!
Khi điều này trở thành một kịch bản không đơn giản , thời gian sẽ bắt đầu viết một công cụ chuyên dụng bằng cách sử dụng ngôn ngữ hiệu quả hơn.
#!/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ó thể bằng cách chạy với một trong
-c sort by command name
-p sort by pid
-m sort by swap values
by default, output is sorted by status's vmsize
:
, dấu gạch chéo ngược, ký tự đại diện hoặc ký tự điều khiển.
[1-9]
trước đây *
để chỉ đếm các đường được đánh số (không self
, cũng không thread-self
)
Name
mục trong /proc/*/status
mã hóa một số những giá trị byte. Hãy thử ví dụ perl -ne 'BEGIN{$0="\n\t\\"} print if /^Name/' /proc/self/status
. Bởi vì nó quá ngắn, thiệt hại có thể được thực hiện với những thứ như perl -ne 'BEGIN{$0="/*/*/../../*/*"} print if /^Name/' /proc/self/status
bị hạn chế khi bạn quên trích dẫn các biến của mình.
Tôi đã điều chỉnh một tập lệnh khác trên web thành tập lệnh dài này:
{ 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 ; }
Sau đó tôi ném vào một cronjob và chuyển hướng đầu ra đến một logfile. Thông tin ở đây giống như tích lũy các Swap:
mục trong tệp smaps, nhưng nếu bạn muốn chắc chắn, bạn có thể sử dụng:
{ 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; }
Đầu ra của phiên bản này có hai cột: pid, số tiền trao đổi. Trong phiên bản trên, tr
dải các thành phần không phải là số. Trong cả hai trường hợp, đầu ra được sắp xếp bằng số theo pid.
Tôi cho rằng bạn có thể đoán đúng bằng cách chạy top
và tìm kiếm các quy trình hoạt động bằng cách sử dụng nhiều bộ nhớ. Làm điều này theo lập trình khó hơn --- chỉ cần nhìn vào các cuộc tranh luận bất tận về các heuristic sát thủ OOM của Linux.
Trao đổi là một chức năng có nhiều bộ nhớ trong sử dụng tích cực hơn được cài đặt, vì vậy thường khó có thể đổ lỗi cho nó trong một quy trình duy nhất. Nếu đó là một vấn đề đang diễn ra, giải pháp tốt nhất là cài đặt thêm bộ nhớ hoặc thực hiện các thay đổi hệ thống khác.
Cung cấp tổng số và tỷ lệ phần trăm cho quá trình sử dụng trao đổi
smem -t -p
Nguồn: https://www.cyberciti.biz/faq/linux-which- Process-is-USE-swap /
Tôi không biết bất kỳ câu trả lời trực tiếp nào là làm thế nào để tìm ra chính xác quá trình đang sử dụng không gian hoán đổi, tuy nhiên, liên kết này có thể hữu ích . Một cái tốt khác ở đây
Ngoài ra, sử dụng một công cụ tốt như htop để xem quá trình nào đang sử dụng nhiều bộ nhớ và tổng số trao đổi đang được sử dụng.
iotop
là một công cụ rất hữu ích. Nó cung cấp số liệu thống kê trực tiếp về I / O và sử dụng trao đổi trên mỗi tiến trình / luồng. Theo mặc định, nó hiển thị trên mỗi luồng nhưng bạn có thể làm iotop -P
để có được mỗi thông tin quy trình. Điều này không có sẵn theo mặc định. Bạn có thể phải cài đặt qua vòng / phút.
Đây là phiên bản xuất ra giống như tập lệnh của @loolotux, nhưng nhanh hơn nhiều (trong khi ít đọc hơn). Vòng lặp đó mất khoảng 10 giây trên máy của tôi, phiên bản của tôi mất 0,009 giây, điều này quan trọng với tôi vì tôi muốn đưa nó vào một trang 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
Kể từ bản vá nhân năm 2015 có thêm SwapPss
( https://lore.kernel.org/patchwork/patch/570506/ ) cuối cùng, người ta có thể nhận được số lượng trao đổi tỷ lệ có nghĩa là nếu một quá trình đã hoán đổi rất nhiều và sau đó nó rẽ nhánh, cả hai quá trình rẽ nhánh sẽ được báo cáo để trao đổi 50% mỗi. Và nếu sau đó rẽ nhánh, mỗi quy trình được tính 33% số trang được hoán đổi, vì vậy nếu bạn tính tất cả các cách sử dụng trao đổi đó với nhau, bạn sẽ có được mức sử dụng trao đổi thực sự thay vì giá trị nhân với số lượng quá trình.
Nói ngắn gọn:
(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)
Cột đầu tiên là pid, cột thứ hai là sử dụng trao đổi trong KiB và phần còn lại của dòng là lệnh đang được thực thi. Số lượng trao đổi giống hệt nhau được sắp xếp theo pid.
Ở trên có thể phát ra các dòng như
awk: cmd. line:1: fatal: cannot open file `15407/smaps' for reading (No such file or directory)
điều đó chỉ có nghĩa là quá trình với pid 15407 đã kết thúc giữa việc nhìn thấy nó trong danh sách /proc/
và đọc smaps
tệp quy trình . Nếu điều đó quan trọng với bạn, chỉ cần thêm 2>/dev/null
vào cuối. Lưu ý rằng bạn cũng có khả năng sẽ mất mọi chẩn đoán có thể khác.
Trong trường hợp ví dụ trong thế giới thực, điều này thay đổi các công cụ khác báo cáo mức sử dụng hoán đổi ~ 40 MB cho mỗi đứa trẻ apache chạy trên một máy chủ thành mức sử dụng thực tế trong khoảng 7-3630 KB thực sự được sử dụng cho mỗi đứa trẻ.