free和top显示可用内存不一致

1. 问题说明

  在国庆的最后一天夜里,服务器突然报警,爆的是内存不够使用了,剩余不到5%。因为该服务器上暂时只运行了一个logstash节点,服务器内存是31g,logstash的jvm堆的大小设置的是24g。看到报警第一反应是,我靠,又发生堆外内存泄漏了?上了服务器,使用top一看,对应的logstash确实只使用24g,对应的其他进程的消耗都很小,加起来不过25g的样子,但是使用free -h 一看,却是已经使用了比较高的内存。显示只有1g的缓存了,对应top的话有5g左右的差距,系统按说不应该占用这么多啊。没办法,先解决报警吧。就临时将logstash的jvm内存调整到22g,然后重启。后面再慢慢的排查这个问题。

下面的排查数据都是重启后的,但是依然可以说明问题
1.使用top,free查看相关信息

top -n1
...
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
24407 deploy    20   0 28.0g  19g  17m S 59.4 61.5   6873:35 java
14900 deploy    20   0 1389m 306m 8632 S 29.7  1.0   2905:33 node
 6352 deploy    20   0  3324 1356  536 R  4.0  0.0   0:00.02 jq-linux64
    1 root      20   0 19348 1192  880 S  0.0  0.0   0:39.53 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    3 root      RT   0     0    0    0 S  0.0  0.0   6:24.71 migration/0
...

这里从RES可以看到用户进程最多消耗的内存是19g+306m 可以认为不到20g
我们再来看看free命令的情况

free -h

             total       used       free     shared    buffers     cached
Mem:           31G        29G       2.3G       204K       392M       4.5G
-/+ buffers/cache:        24G       7.2G
Swap:           0B         0B         0B

可以看到从用户角度看到的进程使用的总内存是24G,这里面有4G左右的偏差,理论上系统不可能占用这么多,而且也会再top中显示的啊。

2.系统内核

cat /etc/issue
CentOS release 6.8 (Final)

cat /proc/version
Linux version 2.6.32-642.6.2.el6.x86_64 (mockbuild@worker1.bsys.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC) ) #1 SMP Wed Oct 26 06:52:09 UTC 2016

2. 折腾之路

这4g的内存到底去了哪里了呢,不知道的话心里总是很痒,难受。首先,这里的表现是topfree显示不一致,想要搞明白这俩命令的统计原理有点费劲,google一下,没有找到。后来同事帮忙用free可用内存偏少关键字找到了这样一篇文章,这才解开了这个问题的面纱。
原来是free相对top没有专门统计Slab。这也是导致两者差别的主要原因。
这个时候想到可以看看内存的具体的数据对照一下
可以使用 cat /proc/meminfo 看到内存的更具体的使用情况

cat /proc/meminfo  |sort -nr -k2
VmallocTotal:   34359738367 kB
VmallocChunk:   34359647340 kB
MemTotal:       32880228 kB
DirectMap1G:    31457280 kB
Committed_AS:   25446604 kB
Active:         22905908 kB
AnonPages:      20760828 kB
Active(anon):   20760796 kB
AnonHugePages:  20178944 kB
CommitLimit:    16440112 kB
Cached:          4765532 kB
# 这里可以看到这一项,确实是4g
Slab:            4262432 kB
SReclaimable:    4225944 kB
Inactive:        3022820 kB
Inactive(file):  3022640 kB
MemFree:         2416988 kB
Active(file):    2145112 kB
DirectMap2M:     2091008 kB
Buffers:          402364 kB
VmallocUsed:       68888 kB
Mapped:            50108 kB
PageTables:        48848 kB
SUnreclaim:        36488 kB
KernelStack:        6176 kB
DirectMap4k:        5992 kB
Hugepagesize:       2048 kB
Shmem:               204 kB
Inactive(anon):      180 kB
Dirty:               152 kB
WritebackTmp:          0 kB
Bounce:                0 kB
...后面还有一些都是0,忽略了

2.1 Slab简介

Slab是内核中使用的数据结构,为了适应更小的数据分配(比页小很多,页通常是4k)。
更加具体的可以参看这里

2.1.1 Slab有两个主要作用:
  • Slab对小对象进行分配,不用为每个小对象分配一个页,节省了空间。
  • 内核中一些小对象创建析构很频繁,Slab对这些小对象做缓存,可以重复利用一些相同的对象,减少内存分配次数。
2.1.2 Slab的信息记录

** 1.Slab的统计信息 **
统计信息记录在/proc/meminfo 中对应的项是
Slab,SReclaimable,SUnreclaim
其中Slab=SReclaimable+SUnreclaim,SReclaimable表示可回收使用的内存。

cat /proc/meminfo  |egrep "Slab|SReclaimable|SUnreclaim"
Slab:            4262724 kB
SReclaimable:    4226028 kB
SUnreclaim:        36696 kB

** 2. Slab 详情 **
Slab详细包含的项存储在/proc/slabinfo 当中

cat /proc/slabinfo|sort -nr -k2

#名称        	   active对象     总对象     对象大小    
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
dentry            20060551      20061020     192            20                 1 : tunables  120	   60  		      8 : slabdata 1003051	     1003051      0
buffer_head       1053268       1053390      104            37                 1 : tunables  120	   60  		      8 : slabdata  28470 	     28470      0
ext3_inode_cache   58426        58445        800             5                 1 : tunables   54	   27  		      8 : slabdata  11689 	     11689      0
size-64            48788        50209         64            59                 1 : tunables  120	   60  		      8 : slabdata    851 	       851    480
radix_tree_node    43129        43204        560             7                 1 : tunables   54	   27  		      8 : slabdata   6172 	      6172      0
size-32            19176        19488         32           112                 1 : tunables  120	   60  		      8 : slabdata    174 	       174      0
ext4_inode_cache   11222        20140       1000             4                 1 : tunables   54	   27  		      8 : slabdata   5035 	      5035      0
inotify_inodm..    10037        10080        120            32                 1 : tunables  120	   60  		      8 : slabdata    315 	       315      0
sysfs_dir_cache     9280         9288        144            27                 1 : tunables  120	   60  		      8 : slabdata    344 	       344      0
selinux_inod..      7610         7844         72            53                 1 : tunables  120	   60  		      8 : slabdata    148 	       148      0
vm_area_struct      7212         9044        200            19                 1 : tunables  120	   60  		      8 : slabdata    476 	       476     24
anon_vma_chain      6202         8701         48            77                 1 : tunables  120	   60  		      8 : slabdata    113 	       113     24
inode_cache         5952         5952        592             6                 1 : tunables   54	   27  		      8 : slabdata    992 	       992      0
proc_inode_cache    5839         6072        656             6                 1 : tunables   54	   27  		      8 : slabdata   1012 	      1012      0
anon_vma            4234         5762         56            67                 1 : tunables  120	   60  		      8 : slabdata     86 	        86      0
filp                2167         4110        256            15                 1 : tunables  120	   60  		      8 : slabdata    274 	       274    480
size-192            1985         2120        192            20                 1 : tunables  120	   60  		      8 : slabdata    106 	       106      0
size-128            1982         2220        128            30                 1 : tunables  120	   60  		      8 : slabdata     74 	        74      0
size-1024           1913         2136       1024             4                 1 : tunables   54	   27  		      8 : slabdata    534 	       534    118

这里主要介绍一下前几个列的含义,如上中文注释,这个文件显示了slab使用的详细分布。这里可以看到dentry 占用的是最大的,他占用的内存可以这样计算
20061020*192/1024=3851727kb 可以得到对应的kb size 。

这个文件还有一个更简单的命令可以看:slabtop

这里可以看到各个维度的总结性信息以及详情,而且自动排序了。同样也是dentry占用最多,但是对应的是cache-size和上面计算出来的不一样,不清楚是不是因为slab是从页中分配出来的所以导致页有空闲导致的。

slabtop -o|head -20
 Active / Total Objects (% used)    : 21372898 / 21401792 (99.9%)
 Active / Total Slabs (% used)      : 1062385 / 1062554 (100.0%)
 Active / Total Caches (% used)     : 99 / 177 (55.9%)
 Active / Total Size (% used)       : 3982075.22K / 3995162.08K (99.7%)
 Minimum / Average / Maximum Object : 0.02K / 0.19K / 4096.00K

  OBJS    ACTIVE   USE OBJ-SIZE  SLABS    OBJ/SLAB CACHE-SIZE NAME
20061120 20060914  99%    0.19K 1003056       20   4012224K   dentry
1054685 1054592    99%    0.10K  28505       37    114020K    buffer_head
 58550  58528      99%    0.78K  11710        5     46840K    ext3_inode_cache
 51271  48907      95%    0.06K    869       59      3476K    size-64
 43218  43152      99%    0.55K   6174        7     24696K    radix_tree_node
 20140  11226      55%    0.98K   5035        4     20140K    ext4_inode_cache
 19488  19057      97%    0.03K    174      112       696K    size-32
 10080  10037      99%    0.12K    315       32      1260K    inotify_inode_mark_entry
  9633   7502      77%    0.20K    507       19      2028K    vm_area_struct
  9288   9280      99%    0.14K    344       27      1376K    sysfs_dir_cache
  8701   6437      73%    0.05K    113       77       452K    anon_vma_chain
  7844   7610      97%    0.07K    148       53       592K    selinux_inode_security
  6114   5955      97%    0.64K   1019        6      4076K    proc_inode_cache

可以看到,这里的dentry 是最多的,那么dentry又是什么东西呢?

2.2 dentry 简介

dentry (directory entry),目录项缓存。也就是内核中用来作为目录的索引,和inode 共同标识了文件系统,inode 存储的是文件的元信息,dentry存储的是文件名加目录的信息,为了快速定位文件。
所以在文件特别多的情况下有可能会导致dentry量比较大。具体介绍参看这里
在文件比较多或者频繁删除创建文件的时候可能会导致dentry比较多。这个是最直接的原因。如何查看系统的文件,inode数量。

df -i

Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/vda1      3276800 714264 2562536   22% /
/dev/vdb       5242880  90647 5152233    2% /home

inodes的数量就代表了dentry的最大数量,可以看到3276800和dentry的数量完全不在一个数量级,所以肯定不是因为系统中的文件太多导致。
但是具体是哪些进程使用了dentry有些难以判断,系统没有直接的信息进行记录。这个时候需要使用大杀器 SystemTap 了。

2.2.1 dentry清空方案

系统默认内存回收配置在/proc/sys/vm/drop_caches中

0:不做任何处理,由系统自己管理 
1:清空pagecache 
2:清空dentries和inodes 
3:清空pagecache、dentries和inodes

所以如果想清空dentry,只需要

echo "2" >  /proc/sys/vm/drop_caches

等待slab有效下降以后,再恢复
echo "0" >  /proc/sys/vm/drop_caches

2.3 SystemTap简介

SystemTap是一个Linux非常有用的调试(跟踪/探测)工具,常用于Linux
内核或者应用程序的信息采集,比如:获取一个函数里面运行时的变
量、调用堆栈,甚至可以直接修改变量的值,对诊断性能或功能问题非
常有帮助。SystemTap提供非常简单的命令行接口和很简洁的脚本语
言,以及非常丰富的tapset和例子。 类似于java的btrace一样,可以用来调试c的调用等。

这个玩意儿太强大了,只是我用的还不是很熟悉,后面有机会了需要继续学习。简单介绍一下安装吧。

2.3.1 SystemTap 安装

安装步骤不算太难,但是网上说的乱七八糟的,很坑,总结一下我的吧。

1. 安装依赖包
SystemTap有一些依赖包,所以要先装这些依赖包。
依赖包有以下3个

  • kernel-debuginfo
  • kernel-debuginfo-common
  • kernel-devel
    这三个包都是和操作系统的内核版本相关的,所以要先查看内核版本
uname -a
Linux 2.6.32-642.6.2.el6.x86_64 #1 SMP Wed Oct 26 06:52:09 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

所以对应的三个包分别是

kernel-debuginfo-2.6.32-642.6.2.el6.x86_64.rpm
kernel-debuginfo-common-x86_64-2.6.32-642.6.2.el6.x86_64.rpm
kernel-devel-2.6.32-642.6.2.el6.x86_64.rpm

建议直接google,然后找到对应的ftp服务器wget下载,我这边也示例以下吧

wget http://ftp.riken.jp/Linux/scientific/6.2/archive/debuginfo/kernel-debuginfo-2.6.32-642.6.2.el6.x86_64.rpm
wget http://ftp.riken.jp/Linux/scientific/6.2/archive/debuginfo/kernel-debuginfo-2.6.32-642.6.2.el6.x86_64.rpm
wget http://ftp.riken.jp/Linux/scientific/6.2/archive/debuginfo/kernel-debuginfo-common-x86_64-2.6.32-642.6.2.el6.x86_64.rpm

然后安装这三个包

rmp -ivh *.rpm

2. yum 安装SystemTap
接下来就简单了
为了部署 SystemTap,需要安装以下两个 RPM 包:

  • systemtap
  • systemtap-runtime
echo "y" | yum install systemtap systemtap-runtime

2.4. 使用systemTap来监控对dentry的使用

2.4.1 从用户进程调用上来统计

这两个函数对应的是对dentry的申请和释放,所以通过对这两个函数的调用可以看到对应的对dentry的使用情况。

cat name_record.stp

probe kernel.function("d_alloc")
{
    printf("%s[%ld] %s %s\n", execname(), pid(), pp(), probefunc())
}
probe kernel.function("d_free")
{
    printf("%s[%ld] %s %s\n", execname(), pid(), pp(), probefunc())
}
probe timer.s(600)
{
    exit()
}

使用命令 stap name_record.stpn > name.log 即可获取相关的信息,name.log中的内容是下面这个样子的。

vim name.log

YDService[26276] kernel.function("d_alloc@fs/dcache.c:968") d_alloc
YDService[26276] kernel.function("d_free@fs/dcache.c:89") d_free
...
05.nodes_only_b[10880] kernel.function("d_free@fs/dcache.c:89") d_free
05.nodes_only_b[10531] kernel.function("d_free@fs/dcache.c:89") d_free
05.nodes_only_b[10531] kernel.function("d_alloc@fs/dcache.c:968") d_alloc
...
curl[10650] kernel.function("d_alloc@fs/dcache.c:968") d_alloc
curl[10650] kernel.function("d_free@fs/dcache.c:89") d_free
curl[10650] kernel.function("d_alloc@fs/dcache.c:968") d_alloc
curl[10650] kernel.function("d_free@fs/dcache.c:89") d_free

可以看到是哪个进程调用了这两个函数。这两个函数是进程可以主动进行调用的。

统计一下对应的进程调用

# 总量26w
wc -l name.log
269715 name.log

# 按照进程排序
awk '{print $1}' name.log|sort  |uniq -c|sort -n -k1  |tail -n30
   1563 05.nodes_only_b[1698]
   1563 05.nodes_only_b[19280]
   1563 05.nodes_only_b[4655]
   1563 05.nodes_only_b[7605]
   1564 05.nodes_only_b[16327]
   1564 05.nodes_only_b[25307]
   1644 kk-superman-age[23735]
   2166 sadc[13116]
   2299 sadc[16307]
   2299 sadc[22276]
   2299 sadc[25301]
   2299 sadc[4659]
   2300 sadc[1697]
   2300 sadc[19281]
   2300 sadc[28249]
   2300 sadc[31200]
   2300 sadc[7594]
   2320 barad_agent[3897]
   4250 falcon-agent[21818]
   5574 curl[27094]
   6503 curl[15143]
   6759 curl[30036]
   6796 curl[516]
   6860 curl[9376]
   6956 curl[6437]
   7024 curl[21094]
   7055 curl[24071]
   7063 curl[18113]
   7148 curl[3494]
  72149 YDService[26276]

可以看到如果按照进程来算的话是YDService 是最多的。先验证一下这个服务。

$ cat name.log |grep "YD"|grep 'd_free'|wc -l
36467
$ cat name.log |grep "YD"|grep 'd_alloc'|wc -l
36572

可以看到这个服务free和alloc的量基本上是一致的,所以没有啥问题。

然后我们再来校验一下curl(因为之前看文档说curl在请求https的时候某写版本是有问题的,所以将所有的curl请求当做一个进程来处理)


$ cat name.log |grep "curl"|grep 'd_alloc'|wc -l
68294
$ cat name.log |grep "curl"|grep 'd_free'|wc -l
738

这一个看,差的好大,估计就是这个了,计算一下按照这个量每分钟产生的大小。
(68294-738)*192/1024/10=1266kb

然后写了一个脚本来记录每分钟的slab,dentry的变换量

#/bin/bash

log_file="$(cd $(dirname $0);pwd)/log_slab.log"
if [ ! -e $log_file ] ;
then 
  echo "time                       slab-kb     dentry-kb      diff    dentry_add" > $log_file
  echo "2019.10.09-21:01:19        2929348      2685424       243924" >> $log_file
fi


dentry_size=$( /usr/bin/slabtop -o|grep dentry |awk '{print $7}'|sed -e "s/K//g")
slab_size=$( cat /proc/meminfo | grep Slab|awk  '{print $2}')
cur_time=$(date +'%Y.%m.%d-%H:%M:%S')
diff_s_d=$(echo "${slab_size}-${dentry_size}"|bc)

lastest_dentry=$(tail -n1 ${log_file}|awk '{print $3}')
diff_dentry=$(echo "${dentry_size} - ${lastest_dentry}"|bc)

res="${cur_time}        ${slab_size}      ${dentry_size}       ${diff_s_d}      ${diff_dentry}"
echo "$res" >> ${log_file}

然后加到定时任务当中

crontab -e 

* * * * * bash /home/xx/dentry_record_/record.sh

后面可以看到每分钟的增量大概是

[deploy@bj3-search-log-logstash01 dentry_record_]$ head -30 log_slab.log
time                       slab-kb     dentry-kb      diff       dentry_add
2019.10.09-21:16:01        2950764      2707576       243188      0
2019.10.09-21:17:01        2951940      2708652       243288      1076
2019.10.09-21:18:01        2953528      2710272       243256      1620
2019.10.09-21:19:01        2955564      2711804       243760      1532
2019.10.09-21:20:01        2956880      2713420       243460      1616
2019.10.09-21:21:01        2958904      2715032       243872      1612

可以看到的是和上面计算的1266kb也是比较接近的。

  这个时候发现我的定时任务中有一个监控脚本,里面是对es集群的监控(每分钟运行一次),curl请求获取es信息使用的是http方式,之前做过一些测试http是不会导致dentry上升的。里面用到https的地方就是如果集群由问题会使用钉钉进行报警,请求钉钉的时候使用的是https的方式。所以一开始没有怀疑这个脚本,这个时候尝试把对应的定时任务关了,结果上面那个脚本显示的结果真的不增加了,看来真的是这个脚本的锅…
这个时候感觉好奇怪,钉钉上也灭有啥信息啊,不可能每分钟都发信息啊。手动运行了一下脚本,发现发送钉钉之后返回的错误码显示是消息格式有问题,所以不会显示,又因为没有发送成功就会每隔一分钟发送一次。。。,因为是一个过时的监控,所以一直没有注意过,结果埋了一个坑。。

  到此,谜底才真正解开,舒服多了,总结一下就是自己写的一个监控脚本有bug,正好触发了curl请求的一个底层bug,导致内核取dentry的分配消耗很大,

2.4.2 curl请求bug的发现

上面的排查过程说明了curl请求的锅,这里聊一下自己验证curl请求的锅的时候使用的脚本。
** 1. 大量发送curl请求的脚本 **
有些时候请求量小的话不太容易看出来

/bin/egrep 'Slab|claim' /proc/meminfo ; /usr/bin/slabtop -o | /bin/egrep 'Slab|SLAB|dent' ; /bin/sh -c 'for i in `seq 300`; do echo -e ".\c" ; /usr/bin/curl --silent https://www.baidu.com > /dev/null  ;done ';echo -e "\n" ; /usr/bin/slabtop -o | /bin/egrep 'Slab|SLAB|dent' ;  /bin/egrep 'Slab|claim' /proc/meminfo
Slab:            2327552 kB
SReclaimable:    2274480 kB
SUnreclaim:        53072 kB
 Active / Total Slabs (% used)      : 577915 / 578012 (100.0%)
  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
7297080 7280735  99%    0.19K 364854       20   1459416K dentry
............................................................................................................................................................................................................................................................................................................

 Active / Total Slabs (% used)      : 581810 / 581956 (100.0%)
  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
7365320 7365320 100%    0.19K 368266       20   1473064K dentry
Slab:            2344412 kB
SReclaimable:    2288276 kB
SUnreclaim:        56136 kB

  测试中发现这个不一定每次都会大量增加,可能因为某些时间点的回收导致的,但是如果是量足够大的话,比如上万次,肯定会增加的比较大。
同时,我们还可以辅助用一个脚本来判断。

** 2. 跟踪dentry分配的细节 **
为了确认有dentry分配,当然,我们可以使用上面的那个跟踪d_alloc的脚本实现,还有一种是可以跟踪dentry具体对应的目录,当然,还是使用强大的systemTap

cat detail_dentry.stp

probe kernel.function("dentry_lru_add")
{
    printf("%s - %s - tid: %d, pid: %ld , ppid: %d, path: /%s\n",
		tz_ctime(gettimeofday_s()), execname(),tid(),pid(), ppid(),
		reverse_path_walk($dentry))
}

使用 stap detail_dentry.stp > d05.log & 来进行记录
然后查看对应文件的记录数据。

head  d05.log

Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895983_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895984_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895985_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895986_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895987_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895988_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895989_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895990_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895991_dOeSnotExist_.db
Fri Oct 11 12:15:02 2019 CST - curl - tid: 30581, pid: 30581 , ppid: 30217, path: /etc/pki/nssdb/.3851895992_dOeSnotExist_.db

根据对应的 ** /etc/pki/nssdb/.3851895989_dOeSnotExist_.db** 关键字也能够google出对应的bug来。

这个bug对应的记录在这里
从这里综合的信息来看,这个bug描述来看,好像是nss的一个bug,出现在3.14.3-4.el6_4.x86_64,如果想要彻底修复,需要经NSS 升级到3.16.1-4
但是实际上在低一些的版本也提供了修复方案,只有是版本大于等于nss-softokn-3.14.3-12.el6 即可通过设置一个变量 export NSS_SDB_USE_CACHE=yes 来解决
查看本机的版本

curl --version
curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2

yum list nss-softokn
...
Installed Packages
nss-softokn.x86_64                                                     3.14.3-23.el6_7                                                       @anaconda-CentOS-201605220104.x86_64/6.8
...

可以看到本机是nss-softokn 版本是3.14.3-23.el6_7 属于bug修复的版本,但不是终极修复版本。
通过在监控脚本的开头添加

export NSS_SDB_USE_CACHE=yes

最终解决问题。

3 . 数据样例附

cat log_slab.log
time                       slab-kb     dentry-kb      diff
2019.10.09-21:01:19        2929348      2685424       243924
2019.10.09-21:01:28        2929204      2685424       243780
2019.10.09-21:01:30        2928804      2685424       243380
2019.10.09-21:01:31        2928736      2685424       243312
2019.10.09-21:06:01        2935132      2691656       243476


#log_file="/home/deploy/search/test_data/systemtap_dependency/dentry_record_/log_slab.log"
log_file="$(cd $(dirname $0);pwd)/log_slab.log"
echo "$log_file"
if [ ! -e $log_file ] ;
 then
   echo "not exist"
   echo "2019.10.09-21:01:19        2929348      2685424       243924" > $log_file
 fi
dentry_size=$( /usr/bin/slabtop -o|grep dentry |awk '{print $7}'|sed -e "s/K//g")
slab_size=$( cat /proc/meminfo | grep Slab|awk  '{print $2}')
cur_time=$(date +'%Y.%m.%d-%H:%M:%S')
diff_s_d=$(echo "${slab_size}-${dentry_size}"|bc)

lastest_dentry=$(tail -n1 ${log_file}|awk '{print $3}')
diff_dentry=$(echo "${dentry_size} - ${lastest_dentry}"|bc)

res="${cur_time}        ${slab_size}      ${dentry_size}       ${diff_s_d}      ${diff_dentry}"
#echo "$res" >> /home/deploy/search/test_data/systemtap_dependency/dentry_record_/log_slab.log
echo "$res" >> ${log_file}

参考

感谢大家分享,让我得以查到这个问题

https://blog.csdn.net/mans1516/article/details/51434408
https://zhuanlan.zhihu.com/p/43133085
https://blog.arstercz.com/centos-%E7%B3%BB%E7%BB%9F-slab-dentry-%E8%BF%87%E9%AB%98%E5%BC%95%E8%B5%B7%E7%B3%BB%E7%BB%9F%E5%8D%A1%E9%A1%BF%E5%88%86%E6%9E%90%E5%A4%84%E7%90%86/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值