筆記: Linux 建立 Swap, 以及 Swap 使用狀況監控, OOM

2019050112:47
 

建立 swap 的方式

#1
先建立一個 2G 空白的檔案以供 swap 使用 (以 root 身份操作)
$ dd if=/dev/zero of=/swapfile bs=1M count=2048
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB) copied, 6.6971 s, 321 MB/s
$ fallocate -l 2G /swapfile

#2
設定 /swapfile 檔案只限 root 才能讀寫
$ chmod 0600 /swapfile

#3
將  /swapfile 檔案設定為 swap格式
$ mkswap /swapfile

#4
正式啟用 swap
$ swapon /swapfile


若想重開機就要自動啟用 swap
得在 /etc/fstab 中加這行
/swapfile swap swap defaults 0 0


 

有關 swap 的使用率

在 /etc/sysctl.conf 檔案中可以設定
vm.swappiness=30    (有可能沒這一行,自行加上)
  再執行 sysctl -p  生效
   0~100, CentOS 7 內定是 30
    數字越大,表示系統會越積極使用 swap
    所以 vm.swappiness=0 就表示禁止使用 swap
    據說設定 0 並非「完全禁用swap」而是盡量、盡量、盡量不使用 swap !!
    ==>設為 0 時,當作業系統記憶體不足時,可能造成記憶體用量大的程式 (如 mysqld ) 優先被作業系統砍掉 oom (Out Of Memory) !! 要小心!!

查看目前的 swappiness 值
$ cat /proc/sys/vm/swappiness
30

另,可以這樣馬上生效
$ echo 50 > /proc/sys/vm/swappiness

參考 :
5.5. 微調虛擬記憶體 - Red Hat



 

關於 Swap 的大小

可參考 RedHat 的建議
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/storage_administration_guide/ch-swapspace
Amount of RAM in the system Recommended swap space Recommended swap space if allowing for hibernation
⩽ 2 GB 2 times the amount of RAM 3 times the amount of RAM
> 2 GB – 8 GB Equal to the amount of RAM 2 times the amount of RAM
> 8 GB – 64 GB At least 4 GB 1.5 times the amount of RAM
> 64 GB At least 4 GB Hibernation not recommended



查詢 swap 的使用情形:
$ swapon -s
Filename                Type        Size    Used    Priority
/mnt/ssd0/swapfile1     file    16777212    9131372    -1
 
$ free -h
              total        used        free      shared  buff/cache   available
Mem:            29G         25G        258M        1.2G        3.7G        2.4G
Swap:           15G        8.7G        7.3G




查詢各個 process 占用 swap 的量

找出那些 process 占用大量 swap

http://northernmost.org/blog/find-out-what-is-using-your-swap/

getswap.sh
#!/bin/bash
# Get current swap usage for all running processes
# Erik Ljungstrom 27/05/2011
SUM=0
OVERALL=0
for DIR in `find /proc/ -maxdepth 1 -type d | egrep "^/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
        echo "PID=$PID - Swap used: $SUM - ($PROGNAME )"
        let OVERALL=$OVERALL+$SUM
        SUM=0

done
echo "Overall swap used: $OVERALL"

這個script 必需以 root 身份執行,執行結果類似:
PID=21477 - Swap used: 0 - (httpd )
PID=21935 - Swap used: 0 - (httpd )
PID=21936 - Swap used: 0 - (httpd )
PID=25008 - Swap used: 0 - (httpd )
PID=25388 - Swap used: 20840 - (memcached )
PID=25731 - Swap used: 13837 - (searchd )
PID=27776 - Swap used: 0 - (kworker/5:0 )
PID=30811 - Swap used: 0 - (kworker/4:1 )
PID=31445 - Swap used: 0 - (kworker/2:2H )
PID=31493 - Swap used: 292 - (mysqld_safe )
PID=32023 - Swap used: 0 - (kworker/2:1H )
PID=32127 - Swap used: 77964 - (mysqld )
PID=32306 - Swap used: 0 - (named )
Overall swap used: 2400564


用這個命令 顯示排序過的資料,比較好閱讀
$ ./getswap.sh | egrep -v "Swap used: 0" |sort -n -k 5
:: ::  ::
PID=22691 - Swap used: 3472 - (manage_accounts )
PID=1123 - Swap used: 3676 - (manage_addresse )
PID=294 - Swap used: 3888 - (systemd-journal )
PID=1120 - Swap used: 5084 - (manage_accounts )
PID=846 - Swap used: 9544 - (polkitd )
PID=1119 - Swap used: 9936 - (tuned )
PID=1095 - Swap used: 12232 - (dhclient )
PID=466 - Swap used: 15752 - (firewalld )
PID=25388 - Swap used: 20840 - (memcached )
PID=25731 - Swap used: 13837 - (searchd )
PID=1 - Swap used: 35500 - (systemd )
PID=32127 - Swap used: 77964 - (mysqld )


另外,用 top 程式也可以類似功能

執行 top 後,按 f 跳到如下畫面
Fields Management for window 1:Def, whose current sort field is %CPU
   Navigate with Up/Dn, Right selects for move then <Enter> or Left commits,
   'd' or <Space> toggles display, 's' sets sort.  Use 'q' or <Esc> to end!

* PID     = Process Id             TIME    = CPU Time            
* USER    = Effective User Name  * SWAP    = Swapped Size (KiB) 游標移到這裡,按空白鍵
* PR      = Priority               CODE    = Code Size (KiB)     
* NI      = Nice Value             DATA    = Data+Stack (KiB)    
* VIRT    = Virtual Image (KiB)    nMaj    = Major Page Faults   
* RES     = Resident Size (KiB)    nMin    = Minor Page Faults   
* SHR     = Shared Memory (KiB)    nDRT    = Dirty Pages Count   
* S       = Process Status         WCHAN   = Sleeping in Function
* %CPU    = CPU Usage              Flags   = Task Flags <sched.h>
* %MEM    = Memory Usage (RES)     CGROUPS = Control Groups      
* TIME+   = CPU Time, hundredths   SUPGIDS = Supp Groups IDs     
* COMMAND = Command Name/Line      SUPGRPS = Supp Groups Names   
  PPID    = Parent Process pid     TGID    = Thread Group Id     
  UID     = Effective User Id      ENVIRON = Environment vars    
  RUID    = Real User Id           vMj     = Major Faults delta  
  RUSER   = Real User Name         vMn     = Minor Faults delta  
  SUID    = Saved User Id          USED    = Res+Swap Size (KiB)
  SUSER   = Saved User Name        nsIPC   = IPC namespace Inode
  GID     = Group Id               nsMNT   = MNT namespace Inode
  GROUP   = Group Name             nsNET   = NET namespace Inode
  PGRP    = Process Group Id       nsPID   = PID namespace Inode
  TTY     = Controlling Tty        nsUSER  = USER namespace Inode
  TPGID   = Tty Process Grp Id     nsUTS   = UTS namespace Inode
  SID     = Session Id          
  nTH     = Number of Threads   
  P       = Last Used Cpu (SMP)




再按 q 返回 top 主畫面
就可以看到各 process 的 swap 使用量
Tasks:  95 total,   1 running,  94 sleeping,   0 stopped,   0 zombie
top - 16:51:03 up 1 day,  9:16,  1 user,  load average: 0.12, 0.07, 0.13
Tasks:  99 total,   1 running,  98 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  5.9 sy,  0.0 ni, 94.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  7494428 total,  3448312 free,  1481176 used,  2564940 buff/cache
KiB Swap:  8388604 total,  8388604 free,        0 used.  5686356 avail Mem 


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                      SWAP
 1850 mysql     20   0 6013868 839088   9128 S   1.5 11.2  10:00.85 mysqld                      77967  
 1181 root      20   0 1730560 1.371g    316 S   1.7  4.7   3612:26 memcached                   31144
   17 root      20   0       0      0      0 S   0.7  0.0   5361:41 rcu_sched                       0
19376 www       20   0 4311124 800308  37436 S   0.7  2.6 162:26.99 httpd                           0
   18 root      20   0       0      0      0 S   0.3  0.0   1573:46 rcuos/0                         0
   20 root      20   0       0      0      0 S   0.3  0.0   1571:28 rcuos/2                         0
   22 root      20   0       0      0      0 S   0.3  0.0   1382:15 rcuos/4                         0
   23 root      20   0       0      0      0 S   0.3  0.0   1148:53 rcuos/5                         0
   24 root      20   0       0      0      0 S   0.3  0.0   1386:56 rcuos/6                         0
  500 root       0 -20       0      0      0 S   0.3  0.0 320:13.53 kworker/0:1H                    0
16493 nobody    20   0 5556776 756068  33764 S   0.3  2.4 124:13.02 httpd                           0
19183 nobody    20   0 5516452 884020  37456 S   0.3  2.9 164:48.98 httpd                           0
21477 nobody    20   0 5545508 824456  37020 S   0.3  2.7 147:07.38 httpd                           0
    2 root      20   0       0      0      0 S   0.0  0.0   1:07.09 kthreadd                        0
    3 root      20   0       0      0      0 S   0.0  0.0  30:35.06 ksoftirqd/0                     0
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                    0
    7 root      rt   0       0      0      0 S   0.0  0.0  13:32.60 migration/0                     0
: : :


還有一個 vmstat 可以持續顯示系統狀態:
$ vmstat 1 20   參數1:秒數,參數2:連續顯示幾次
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0 9301876 420408      0 3770532    0    0   179    46    0    0  2  1 96  0  0
 0  0 9301876 419852      0 3770884    0    0   296     0 1083 1835  1  1 98  1  0
 0  0 9301876 419440      0 3771256    0    0   276   564 1020 1814  1  0 99  0  0
 0  0 9301876 419440      0 3771376    0    0   104     0 1306 2331  1  1 98  0  0
 0  0 9301876 418200      0 3772672    0    0  1180   248 1974 3424  1  1 97  0  0
 0  0 9301876 417524      0 3773180    0    0   808   863 2095 3724  1  1 97  1  0
 1  1 9301876 402636      0 3788004    0    0 15112    12 1434 2449  1  1 95  3  0
 0  0 9301876 397192      0 3793416    0    0  5120   864 2480 4369  1  1 94  3  0
 0  0 9301876 392488      0 3798220    0    0  4772   224 2818 4721  2  1 96  1  0
 0  0 9301876 391984      0 3798784    0    0   736   248 2462 4250  2  1 96  1  0




 

OOM (Out Of Memory)

  • /proc/$PID/oom_adj                kernel 2.6.36起 用這個 (可不管oom_score_adj )  範圍 -1000 ~ 1000
  • /proc/$PID/oom_score            oom分數,數字越大 越可能被 Killer 砍掉
  • /proc/$PID/oom_score_adj


     
找出最可能被 oom killer 刪除的程式
 參考:理解和配置 Linux 下的 OOM Killer

oomscore.sh
#!/bin/bash
    printf "PID   score  process\n"
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do
    printf "%4d %6d %s\n" \
        "$(cat $proc/oom_score)" \
        "$(basename $proc)" \
        "$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)"
done 2>/dev/null | sort -nr | head -n 10


執行結果
$ sh oomscore.sh
PID   score  process
237   32127  /usr/local/mysql/bin/mysqld 
 30   25388  /usr/local/bin/memcached -d -u root -m 2000 -l 127
 18   19183  /home/www/httpd2439/bin/httpd -k start
 17    9489  /home/www/httpd2439/bin/httpd -k start
 17   21936  /home/www/httpd2439/bin/httpd -k start
 17   21477  /home/www/httpd2439/bin/httpd -k start
 16   21935  /home/www/httpd2439/bin/httpd -k start
 16   19376  /home/www/httpd2439/bin/httpd -k start
 16   19182  /home/www/httpd2439/bin/httpd -k start 

score 數字越大,被系統刪掉的機率越大



怎样避免mysqld被oom-killer杀死?