如何检查服务器上消耗资源的程序是那个

对于一台linux服务器来讲,总共有三种资源 CPU、磁盘、内存。三种资源消耗到红线的状态也不同

内存检查

如果是内存将要耗尽,服务器的响应速度会变慢,当前连接会话输入命令时会有相依延迟的现象,启动一个新的程序会出现 os:memory 报错,此时执行free命令查看

bash 复制代码
[root@node4 ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           1.9G        108M        1.7G        8.6M        143M        1.7G
Swap:          2.0G          0B        2.0G

看最后一列 available 表示还有多少内存可以用来分配,如果它没多少或者随着查询快速下降,此时就表示存在程序吃内存

此时,使用 vmstat 查询系统资源监控,每隔 1 秒输出一次

bash 复制代码
[root@node4 ~]# vmstat 1
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      0 1773332   2108 145276    0    0    31     4   31   35  0  0 100  0  0
 0  0      0 1773332   2108 145276    0    0     0     0   52   47  0  0 100  0  0
 0  0      0 1773332   2108 145276    0    0     0     0   36   33  0  0 99  0  0
 0  0      0 1773332   2108 145276    0    0     0     0   49   43  0  0 100  0  0

监控中,r 表示有多少个进程在等待核时,b 表示有多少进程在阻塞。

memory 下的四个指标中,free 和 直接用 free -h 命令看到的结果基本是一样的,这里的单位是 kb,但往往它会存在很小的可能,因为linux对内存的使用遵循能用就用的原则,将空闲内存大量用作各种缓存,所以会存在服务器上没运行很多繁杂任务,但是这里的剩余内存就是很小。当确实存在吃内存的程序时,free 会明显下降,但是 buff cache也会下降,也就是说 buff cache 它并不包含进程消耗内存数量,它仅仅只是内核对磁盘读取的缓存,当其他进程大量消耗内存时,会挤压它们两个使用额度。

swap 下的 si 和 so 代表交换内存的换入和换出,在内存紧张且没有关闭交换分区能力时,会频繁变动,且 swpd 值也会较大,它表示当前有多少数据存放在用来做交换内存的磁盘以及文件中。

bi 和 bo 表示当前系统每秒共向磁盘读取和写入多少数据块,它包含了交换分区的数量。

system 下的 in 记录当前有多少个需要cpu注意的中断信号,这里说的中断是值进程完成、文件写入完成、进程由于错误而中断等等所有需要cpu决策的情况,一般不重要,cs 是内核上下文切换次数指标,也就是在不同进程之间切换,in 会影响 cs 的数量,但不是一比一的数量关系。

cpu 下的指标中,us 表示 cpu 在用户态进程(普通应用程序、计算任务)的时间百分比,sy 表示 cpu 在处理内核态(处理系统调用、管理内存、处理中断、I/O 等)的时间百分比,id 表示 cpu 处于完全空闲时间的百分比,wa 表示 cpu 因为 io 未完成而陷入等待的时间百分比,st 表示如果当前服务器是个虚拟机的话,cpu 被宿主机挪用的时间百分比

言归正传,当内存进入红线,交换分区的指标会频繁变动,缓存指标会减少,free 可用内存也会很小。此时需要使用 top 命令查询内存消耗情况,进入后按英文大写 M 会进入%MEM内存倒排

bash 复制代码
top - 17:30:44 up  1:20,  1 user,  load average: 0.00, 0.01, 0.01
Tasks: 116 total,   2 running, 114 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2031912 total,  1765472 free,   114056 used,   152384 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  1743048 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND    
   923 root      20   0  562404  16560   5876 S   0.0  0.8   0:00.51 tuned      
   956 root      20   0  158860  12016    712 S   0.0  0.6   0:00.00 kadmind    
   685 polkitd   20   0  534132  10976   4600 S   0.0  0.5   0:00.01 polkitd    
   683 root      20   0  471824   8852   6580 S   0.0  0.4   0:00.11 NetworkMa+ 
     1 root      20   0  128220   6860   4076 S   0.0  0.3   0:00.61 systemd    
   691 root      20   0  305092   6128   4764 S   0.0  0.3   0:03.42 vmtoolsd   
   684 root      20   0   99620   6076   4468 S   0.0  0.3   0:00.01 VGAuthSer+ 
   688 root      20   0  214248   5580   3208 S   0.0  0.3   0:00.25 rsyslogd   
  1034 root      20   0  145716   5200   3924 S   0.0  0.3   0:00.15 sshd       
   514 root      20   0   46952   5036   2836 S   0.0  0.2   0:00.04 systemd-u+ 
   513 root      20   0  190792   4140   2572 S   0.0  0.2   0:00.00 lvmetad    
   922 root      20   0  106012   4076   3096 S   0.0  0.2   0:00.00 sshd       
  1015 postfix   20   0   89728   4016   3012 S   0.0  0.2   0:00.00 qmgr       
  1014 postfix   20   0   89660   3992   2988 S   0.0  0.2   0:00.03 pickup     
   929 root      20   0  154584   3616    824 S   0.0  0.2   0:00.00 krb5kdc    
   491 root      20   0   36828   2760   2444 S   0.0  0.1   0:00.04 systemd-j+ 
  1126 root      20   0  157688   2132   1496 R   0.0  0.1   0:00.04 top       

PID 是进程ID。USER 是启动进程的用户。PR 是内核视角的瞬时任务优先级,数字越小优先级越高。NI 是任务本身的优先级,范围 -20 到 19 同样数字越小优先级越高,它会影响 PR。VIRT 使用虚拟内存总量 。RES 使用物理内存总量。SHR 和其他进程共享的内存总量。S 是进程状态,R 表示运行,S 表示可自主的中断,D 表示不可自主的中断(也就是当前进程在等一个非自己可控的事情的结果,比如磁盘不响应等等这些它自己不是自己想中断的状态),Z 表示以结束但资源还没来的急回收,T 表示被暂停。%CPU 表示上次筛选当现在占用 cpu 的时间。%MEM 表示进程占物理内存的百分比。TIME+ 表示进程自启动以来累计使用的 CPU 时间,格式 分:秒.百分秒,精度比 TIME 高。COMMAND 表示进程的命令行名称或启动命令,如果你想看完整命令,键入小写 c

排查内存问题,主要看 RES ,你要记录下目标进程的 PID,top命令展示的是个十进制数,你需要更具不同类型的程序做处理,比如目标是个Java程序,就需要 printf 命令转换成十六进制

bash 复制代码
# 如果这个Java程序用的是多线程,你要额外查询子进程的PID,内存排序的操作是一样的
top -Hp Java程序的十进制PID

#随后将目标PID转十六进制
printf "%x\n" 目标PID

随后使用 jstack 命令导出目标进程ID的系统日志快照。对于Java程序来讲在文件中搜索十六进制的进程ID,就能看到堆栈信息,就和Java报错格式一样能看到是那个类哪行代码触发的堆栈信息,以及进程运行的状态

bash 复制代码
jstack 目标十进制PID > 储存到文件

如果不是个Java,就不需要这么麻烦。

对于 C 原生程序,你需要安装一个工具

bash 复制代码
yum install valgrind

# 随后启动一个的目标 c 程序的伴生进程
valgrind --tool=massif 目标程序路径

在运行一段实际后,结束 c 程序,在运行valgrind的路径下会生成一个 massif.out.<PID> 的文件,使用分析命令,即可查看堆内存使用报告
ms_print massif.out.<PID>

如果是个 python程序,需要安装工具

bash 复制代码
pip install memray

# 随后和 c 程序一样,附件到目标进程一个伴生程序。运行足够时间后,按 Ctrl+C 停止采集
memray attach --aggregate -o 结果输出到的路径 进程PID

# 结果数据有两种使用方式
memray table 结果输出到的路径 --sort 文本路径   # 以文本图标的方式,看哪个函数累计分配最多
memray flamegraph 结果输出到的路径 -o flame.html   # 生成火焰图,浏览器看

如果你想一招鲜,linux有个通用工具,但是注意这个工具需要4.1以上的内核

bash 复制代码
yum install bcc-tools

/usr/share/bcc/tools/memleak -p 11111 -t -a 5
# -p 指定进程,-t 显示调用栈,-a 5 输出前 5 个

# 持续观察一段时间,它会定期报告哪些分配点累积了最多内存却没有释放
Attaching to pid 11111, Ctrl+C to end.
[21:03:12] Top 5 stacks with outstanding allocations:
  8 outstanding allocations of total 50331648 bytes:
  -> b'allocate_token_bucket' + 0x3f  [rust_service; addr=0x4221a0]
  -> b'handle_connection' + 0x1a2  [rust_service; addr=0x4055e2]
  ...


输出直接指出函数名 allocate_token_bucket 和 handle_connection。
对于目标进程是原生二进制文件,可以直接用命令 `addr2line -e 进程的二进制执行文件 0x4221a0 `就能定位到具体源文件中的行号
addr2line 命令是专门用来查询二进制地址在一个二进制可执行文件中的位置的

CPU检查

如果你查看 top 命令的监控时,发现内存相关的检查点没有特殊的异常但是服务很卡,就去看 cpu 运行百分比,键入大写 P 就可以按照 %CPU 排序

bash 复制代码
Tasks: 114 total,   1 running, 113 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2031912 total,  1525240 free,   116544 used,   390128 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  1715032 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND    
  1148 root      20   0       0      0      0 S   0.3  0.0   0:01.08 kworker/2+ 
     1 root      20   0  128220   6860   4076 S   0.0  0.3   0:00.67 systemd    
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kthreadd   
     3 root      20   0       0      0      0 S   0.0  0.0   0:00.04 ksoftirqd+ 
     5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0+ 
     6 root      20   0       0      0      0 S   0.0  0.0   0:00.26 kworker/u+ 
     7 root      rt   0       0      0      0 S   0.0  0.0   0:00.00 migration+ 
     8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh     
     9 root      20   0       0      0      0 S   0.0  0.0   0:00.97 rcu_sched  
    10 root      rt   0       0      0      0 S   0.0  0.0   0:00.05 watchdog/0 
    11 root      rt   0       0      0      0 S   0.0  0.0   0:00.03 watchdog/1 
    12 root      rt   0       0      0      0 S   0.0  0.0   0:00.00 migration+ 
    13 root      20   0       0      0      0 S   0.0  0.0   0:00.01 ksoftirqd+ 
    15 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1+ 
    16 root      rt   0       0      0      0 S   0.0  0.0   0:00.04 watchdog/2 
    17 root      rt   0       0      0      0 S   0.0  0.0   0:00.00 migration+ 
    18 root      20   0       0      0      0 S   0.0  0.0   0:00.00 ksoftirqd+

随后的排查思路和上面的内存排查差不多,比如 Java 从程序都是导出堆栈日志,查看当前执行的是什么代码,就能知道哪里在吃CPU

C 原生程序,用perf工具

bash 复制代码
yum install -y perf

# 录制 30 秒,-g 记录调用栈 ,-p 进程号
perf record -p 3456 -g -- sleep 30

# 30秒后,使用report查看记录到等信息
perf report

Samples: 120K of event 'cycles', Event count (approx.): 48000000000
  Children      Self  Symbol
+   99.00%     0.00%  [.] main
+   98.50%     0.00%  [.] process_request
+   97.20%    90.30%  [.] hash_loop  <--- 这里占用了 90% CPU

perf工具还可以实时看看cpu热点,相当于看cpu的一招鲜办法

bash 复制代码
# 直接执行看的是所有,可以带上 -p  看某个进程的
[root@node4 opt]# perf top
Samples: 56  of event 'cpu-clock', 4000 Hz, Event count (approx.): 7871188 lost:
Overhead  Shared Object     Symbol                                              
  49.58%  [kernel]          [k] _raw_spin_unlock_irqrestore                     
  11.40%  [kernel]          [k] generic_exec_single                             
   6.12%  [kernel]          [k] mpt_put_msg_frame                               
   3.76%  [kernel]          [k] e1000_xmit_frame                                
   2.85%  [kernel]          [k] kallsyms_expand_symbol.constprop.1              
   2.78%  [kernel]          [k] rcu_idle_exit                                   
   2.13%  [kernel]          [k] run_timer_softirq                               
   1.43%  [kernel]          [k] __memcpy                                        
   1.43%  [kernel]          [k] __x2apic_send_IPI_mask                          
   1.43%  [kernel]          [k] finish_task_switch                              
   1.43%  [kernel]          [k] format_decode                                   
   1.43%  [kernel]          [k] module_get_kallsym                              
   1.43%  [kernel]          [k] number.isra.2                                   
   1.43%  [kernel]          [k] queue_delayed_work_on                           
   1.43%  [kernel]          [k] smp_call_function_many                          
   1.43%  [kernel]          [k] strlcpy                                         
   1.43%  [kernel]          [k] vsnprintf                                       
   1.43%  libc-2.17.so      [.] _IO_getdelim                                    
   1.43%  libc-2.17.so      [.] __libc_calloc                                   
   1.43%  perf              [.] __dso__load_kallsyms                            
   1.43%  perf              [.] hex2u64   

Overhead 该函数消耗的 CPU 时间占比,所有行加起来接近 100%。Shared Object 函数所在的二进制文件或库,[kernel] = Linux 内核,libc-2.17.so = C 标准库,perf = perf 工具自身代码,普通程序名(如 java, nginx)会直接显示。Symbol 具体的函数名。[k] 表示内核空间函数,[.] 表示用户空间函数。

磁盘检查

同理,如果你发现 top 命令中磁盘写入读出的数据块很高,也可以定位程序。不过磁盘通常不会检查怎么细,因为磁盘的影响范围比较局限,它不会把整个服务器拖垮,最多只会使得某一个路径在其他程序读取它时陷入长久的IO等待,严重的时候读取的程序会报一个内核GC错误

但如果你确实需要看是那个具体的代码在操作数据块,linux也能看,用的也是 perf

bash 复制代码
# 录制 10 秒,关注对应进程所有"通用块层 I/O 请求发出"的内核事件
perf record -e block:block_rq_issue -p 7766 -g -- sleep 10

# 查看报告,包含调用栈
perf report --stdio

[root@node4 opt]# perf record -e block:block_rq_issue -p 1148 -g -- sleep 10
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.011 MB perf.data (5 samples) ]
[root@node4 opt]# perf report --stdio
# To display the perf.data header info, please use --header/--header-only option
#
#
# Total Lost Samples: 0
#
# Samples: 5  of event 'block:block_rq_issue'
# Event count (approx.): 5
#
# Children      Self  Trace output                                              
# ........  ........  ..........................................................
#
   100.00%   100.00%  0,0 R 8 (4a 01 00 00 10 00 00 00 08 00) 0 + 0 [kworker/2:0
            |
            ---ret_from_fork
               kthread
               worker_thread
               process_one_work
               disk_events_workfn
               disk_check_events
               sr_block_check_events
               cdrom_check_events
               sr_check_events
               scsi_execute_req_flags
               scsi_execute
               blk_execute_rq
               blk_execute_rq_nowait
               __blk_run_queue
               scsi_request_fn
               blk_peek_request



#
# (Tip: Profiling branch (mis)predictions with: perf record -b / perf report)
#

磁盘影响最恶劣的也就至于一个磁盘自身坏了,这种你写一个文件进去,写入失败与否就知道磁盘坏没坏了


有时候对于服务器的检查不是上面这种出了问题,才做后置检查。而是判断这台服务器能不能满足应用的需求,比如说现在有台服务器,让你判断磁盘的 QPS 能不能达到预期要求,这个时候 top命令就不行了,就需要使用另外的命令工具了,可以看-》https://blog.csdn.net/dudadudadd/article/details/144566868

相关推荐
时空自由民.2 小时前
Linux,ESP IDF,NuttX OS使用的项目编译管理构建体系Kconfig + Kbuild(或基于 Make/CMake 的构建系统)
linux·运维·服务器
LIO2 小时前
Vue Router 进阶:深入用法与最佳实践
前端·vue-router
开开心心就好2 小时前
一款既是直播工具又是浏览器的软件
linux·运维·服务器·智能手机·逻辑回归·excel·最小二乘法
Hilaku2 小时前
做了 6 年前端,技术不差却拿不到 Offer?
前端·javascript·程序员
古茗前端团队2 小时前
钉钉小程序蓝牙打印探索与实践
前端·蓝牙
tangyal2 小时前
DNS(BIND) 正反向解析文件的部署实验
linux·运维·服务器·bind·dns正向解析·dns反向解析
LIO2 小时前
一文看懂 Vue Router:精简、易懂、直接用
前端·vue-router
Fcy6482 小时前
Linux下 进程控制(三) —— ⾃主Shell命令⾏解释器
linux·服务器
Highcharts.js2 小时前
技术组合分析:Highcharts 的数据集成能力解析
java·前端·金融·echarts·saas·bi·highcharts