自定义一个一键获取Linux系统状态信息的脚本

之前博客分享过一个Linux云服务器的一键测速脚本,可以很方便的来测试我们系统的IO网络等信息。对于系统状态信息的话我们一般使用top命令也能够获取到,但这次分享一个自定义属于我们自己的获取Linux内存、磁盘IO、CPU使用率、负载等信息的脚本~

环境:CentOS 7 x64

先要准备好下面这个工具,不然的话磁盘IO部分的信息得不到哦

yum -y install sysstat

这次主要是分享获取信息的思路,也就是俗话说的"授人以渔",不同OS下关于各个方面的会有一点点出入,但是看完文章之后相信你也能针对自己的系统改出来的~~

一、简单呈现

脚本内容:

IP=`ifconfig | grep inet | grep -vE 'inet6|127.0.0.1' | awk '{print $2}'`  
echo "IP地址:"$IP  

cpu_num=`grep -c "model name" /proc/cpuinfo`  
echo "cpu总核数:"$cpu_num  

cpu_user=`top -b -n 1 | grep Cpu | awk '{print $2}' | cut -f 1 -d "%"`  
echo "用户空间占用CPU百分比:"$cpu_user  

cpu_system=`top -b -n 1 | grep Cpu | awk '{print $4}' | cut -f 1 -d "%"`  
echo "内核空间占用CPU百分比:"$cpu_system  

cpu_idle=`top -b -n 1 | grep Cpu | awk '{print $8}' | cut -f 1 -d "%"`  
echo "空闲CPU百分比:"$cpu_idle  

cpu_iowait=`top -b -n 1 | grep Cpu | awk '{print $10}' | cut -f 1 -d "%"`  
echo "等待输入输出占CPU百分比:"$cpu_iowait  

cpu_interrupt=`vmstat -n 1 1 | sed -n 3p | awk '{print $11}'`  
echo "CPU中断次数:"$cpu_interrupt  

cpu_context_switch=`vmstat -n 1 1 | sed -n 3p | awk '{print $12}'`  
echo "CPU上下文切换次数:"$cpu_context_switch  

cpu_load_15min=`uptime | awk '{print $12}' | cut -f 1 -d ','`  
echo "CPU 15分钟前到现在的负载平均值:"$cpu_load_15min  

cpu_load_5min=`uptime | awk '{print $11}' | cut -f 1 -d ','`  
echo "CPU 5分钟前到现在的负载平均值:"$cpu_load_5min  

cpu_load_1min=`uptime | awk '{print $10}' | cut -f 1 -d ','`  
echo "CPU 1分钟前到现在的负载平均值:"$cpu_load_1min  
 
cpu_task_length=`vmstat -n 1 1 | sed -n 3p | awk '{print $1}'`  
echo "CPU任务队列长度:"$cpu_task_length  
    
mem_total=`free | grep Mem | awk '{print $2}'`  
echo "物理内存总量:"$mem_total  

mem_sys_used=`free | grep Mem | awk '{print $3}'`  
echo "已使用内存总量(操作系统):"$mem_sys_used  
 
mem_sys_free=`free | grep Mem | awk '{print $4}'`  
echo "剩余内存量(free部分):"$mem_sys_free  
   
mem_sys_free2=`free | grep Mem | awk '{print $6}'`  
echo "剩余内存量(buffer/cached部分):"$mem_sys_free2  
   
mem_swap_total=`free | grep Swap | awk '{print $2}'`  
echo "交换分区总大小:"$mem_swap_total  
 
mem_swap_used=`free | grep Swap | awk '{print $3}'`  
echo "已使用交换分区大小:"$mem_swap_used  
   
mem_swap_free=`free | grep Swap | awk '{print $4}'`  
echo "剩余交换分区大小:"$mem_swap_free  
   
echo "指定设备(/dev/vda)的统计信息"  

disk_sda_rs=`iostat -kx | grep vda| awk '{print $4}'`  
echo "每秒向设备发起的读请求次数:"$disk_sda_rs  

disk_sda_ws=`iostat -kx | grep vda| awk '{print $5}'`  
echo "每秒向设备发起的写请求次数:"$disk_sda_ws  

disk_sda_avgqu_sz=`iostat -kx | grep vda| awk '{print $9}'`  
echo "向设备发起的I/O请求队列长度平均值"$disk_sda_avgqu_sz  

disk_sda_await=`iostat -kx | grep vda| awk '{print $10}'`  
echo "每次向设备发起的I/O请求平均时间:"$disk_sda_await  

disk_sda_svctm=`iostat -kx | grep vda| awk '{print $11}'`  
echo "向设备发起的I/O服务时间均值:"$disk_sda_svctm  

disk_sda_util=`iostat -kx | grep vda| awk '{print $12}'`  
echo "向设备发起I/O请求的CPU时间百分占比:"$disk_sda_util  

在腾讯云轻量服务器2核4G内存的CentOS 7上运行结果:

(base) [root@VM-12-4-centos ~]# ./get_status.sh 
IP地址:10.0.12.4    # 获取到的是腾讯云的内网IP
cpu总核数:2
用户空间占用CPU百分比:0.0
内核空间占用CPU百分比:3.1
空闲CPU百分比:96.8
等待输入输出占CPU百分比:0.0
CPU中断次数:7
CPU上下文切换次数:7
CPU 15分钟前到现在的负载平均值:0.10
CPU 5分钟前到现在的负载平均值:0.07
CPU 1分钟前到现在的负载平均值:0.05
CPU任务队列长度:3
物理内存总量:3880192
已使用内存总量(操作系统):662168
剩余内存量(空闲部分):258052
剩余内存量(活跃部分):2958916
交换分区总大小:0
已使用交换分区大小:0
剩余交换分区大小:0
指定设备(/dev/sda)的统计信息
每秒向设备发起的读请求次数:0.02
每秒向设备发起的写请求次数:2.54
向设备发起的I/O请求队列长度平均值0.00
每次向设备发起的I/O请求平均时间:2.31
向设备发起的I/O服务时间均值:1.33
向设备发起I/O请求的CPU时间百分占比:2.32

二、原理部分

这个脚本最核心的指令就是grep等过滤器的应用,例如对于IP地址部分,我们通常使用ifconfig指令来查看详细信息

(base) [root@VM-12-4-centos ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.12.4  netmask 255.255.252.0  broadcast 10.0.15.255
        inet6 fe80::5054:ff:febe:5343  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:be:53:43  txqueuelen 1000  (Ethernet)
        RX packets 54575414  bytes 6480746019 (6.0 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 74744841  bytes 9002036667 (8.3 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 542694  bytes 44695694 (42.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 542694  bytes 44695694 (42.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

1.IP地址部分

我们的脚本可以写为

IP=`ifconfig | grep inet | grep -vE 'inet6|127.0.0.1' | awk '{print $2}'`  
echo "IP地址:"$IP  

其中:

  • ifconfig | grep inet可以过滤出含有inet的那一行
  • grep -vE 'inet6|127.0.0.1'则将上面那一步的结果进一步过滤,这次是清除带有inet6和回环地址的两行
  • awk指令可以用于做字符串的空格分隔,例如awk '{print $2}'则将上面过滤结果的行中,选择第二个内容进行输出,也就是我们想得到的IP地址了~
  • 最后就是使用shell脚本中最经典的echo命令,来打印出上面对变量(IP)进行赋值之后的结果~

2.CPU部分

核心数部分

通过cat /proc/cpuinfo命令我们可以查看CPU的详细信息,之后可以从中提取到核心数信息

cpu_num=`grep -c "model name" /proc/cpuinfo`  
echo "cpu总核数:"$cpu_num  

其中grep -c中的c可以理解为count,也就是统计有多少个model name,这样就可以得到核心数了

利用率部分

可以使用我们熟知的top命令来获取信息,并且从中截取信息

cpu_user=`top -b -n 1 | grep Cpu | awk '{print $2}' | cut -f 1 -d "%"`  
echo "用户空间占用CPU百分比:"$cpu_user  
   
cpu_system=`top -b -n 1 | grep Cpu | awk '{print $4}' | cut -f 1 -d "%"`  
echo "内核空间占用CPU百分比:"$cpu_system  

cpu_idle=`top -b -n 1 | grep Cpu | awk '{print $8}' | cut -f 1 -d "%"`  
echo "空闲CPU百分比:"$cpu_idle  
    
cpu_iowait=`top -b -n 1 | grep Cpu | awk '{print $10}' | cut -f 1 -d "%"`  
echo "等待输入输出占CPU百分比:"$cpu_iowait  

其中top -b -n 1中:

b代表处理top的输出成为适合打印到文件的样式,可以用这个创建日志等

n代表退出top前打印次数(类似于ping里面的-n)

因此这个指令代表使用top指令并只打印一次,结果如下

(base) [root@VM-12-4-centos ~]# top -b -n 1
top - 01:12:25 up 30 days,  3:43,  1 user,  load average: 0.12, 0.08, 0.08
Tasks: 118 total,   1 running, 117 sleeping,   0 stopped,   0 zombie
%Cpu(s):  9.7 us,  3.2 sy,  0.0 ni, 87.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  3880192 total,   260992 free,   659368 used,  2959832 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  2924252 avail Mem 

...省略

这时候又可以像上面一样提取信息了,不过这次出现了cut指令

cut -f 1 -d "%" 解释:
-d  "%" 是以%作为分隔符   
-f 1显示以:分割每一行的第一段内容  

因此对awk后的第2段内容应用这个就是显示9.7了

剩下的内容也是一样的道理,想要什么信息我们就可以自己加上,其对应名字为:

#us 用户空间占用CPU百分比  
#sy 内核空间占用CPU百分比  
#ni 用户进程空间内改变过优先级的进程占用CPU百分比  
#id 空闲CPU百分比  
#wa 等待输入输出的CPU时间百分比  
#hi 硬件中断  
#si 软件中断  
CPU负载部分

查看负载信息源自于uptime指令

(base) [root@VM-12-4-centos ~]# uptime
 12:33:23 up 30 days, 15:04,  1 user,  load average: 0.25, 0.17, 0.14

其中可以显示的内容包括服务器运行时间、当前用户数量和3个负载值,之后我们按上面的思路继续进行分隔

对于负载值的含义(携程面试题):

核心数平均负载含义
10.5有50%的CPU是空闲状态
11CPU刚好被完全占用
12至少有50%的进程抢不到CPU资源
22CPU刚好被完全占用

可见,2个CPU表明系统负荷可以达到2.0,此时每个CPU都达到100%的工作量。推广开来,n个CPU的电脑,可接受的系统负荷最大为n.0。

根据某运维大佬的博客,系统负荷的经验法则为:

1.0是系统负荷的理想值吗?

不一定,系统管理员往往会留一点余地,当这个值达到0.7,就应当引起注意了。经验法则是这样的:

当系统负荷持续大于0.7,你必须开始调查了,问题出在哪里,防止情况恶化。

当系统负荷持续大于1.0,你必须动手寻找解决办法,把这个值降下来。

当系统负荷达到5.0,就表明你的系统有很严重的问题,长时间没有响应,或者接近死机了。你不应该让系统达到这个值。

理解了负载之后,我们再来写成脚本获取负载的值吧

# 获取CPU15分钟前到现在的负载平均值  
cpu_load_15min=`uptime | awk '{print $12}' | cut -f 1 -d ','`  
echo "CPU 15分钟前到现在的负载平均值:"$cpu_load_15min  
   
# 获取CPU5分钟前到现在的负载平均值  
cpu_load_5min=`uptime | awk '{print $11}' | cut -f 1 -d ','`  
echo "CPU 5分钟前到现在的负载平均值:"$cpu_load_5min  
   
# 获取CPU1分钟前到现在的负载平均值  
cpu_load_1min=`uptime | awk '{print $10}' | cut -f 1 -d ','`  
echo "CPU 1分钟前到现在的负载平均值:"$cpu_load_1min  

3.内存信息部分

在Linux系统中对于内存的状态信息主要通过free命令来获取

(base) [root@VM-12-4-centos ~]# free
              total        used        free      shared  buff/cache   available
Mem:        3880192      659320      255812         928     2965060     2924300
Swap:             0           0           0

根据查阅到的资料,应用程序可用内存的定义为

available RAM for programs = free + buffers + cached

对于上面的信息,使用同样的思路进行过滤

mem_total=`free | grep Mem | awk '{print $2}'`  
echo "物理内存总量:"$mem_total  

mem_sys_used=`free | grep Mem | awk '{print $3}'`  
echo "已使用内存总量(操作系统):"$mem_sys_used  
 
mem_sys_free=`free | grep Mem | awk '{print $4}'`  
echo "剩余内存量(free部分):"$mem_sys_free  
   
mem_sys_free2=`free | grep Mem | awk '{print $6}'`  
echo "剩余内存量(buffer/cached部分):"$mem_sys_free2  
   
mem_swap_total=`free | grep Swap | awk '{print $2}'`  
echo "交换分区总大小:"$mem_swap_total  
 
mem_swap_used=`free | grep Swap | awk '{print $3}'`  
echo "已使用交换分区大小:"$mem_swap_used  
   
mem_swap_free=`free | grep Swap | awk '{print $4}'`  
echo "剩余交换分区大小:"$mem_swap_free  

4.磁盘IO信息部分

使用这个部分确保安装了sysstat,没有的话使用下面的指令安装

yum -y install sysstat         # for CentOS
apt-get -y install sysstat  # for Ubuntu
(base) [root@VM-12-4-centos ~]# iostat
Linux 3.10.0-1127.19.1.el7.x86_64 (VM-12-4-centos)     04/23/2021     _x86_64_    (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           1.97    0.00    1.28    0.03    0.00   96.72

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
vda               2.56         0.25        25.29     662494   66963268
scd0              0.00         0.00         0.00       6222          0

提取信息为:

echo "指定设备(/dev/sda)的统计信息"  
# 每秒向设备发起的读请求次数  
disk_sda_rs=`iostat -kx | grep sda| awk '{print $4}'`  
echo "每秒向设备发起的读请求次数:"$disk_sda_rs  
   
# 每秒向设备发起的写请求次数  
disk_sda_ws=`iostat -kx | grep sda| awk '{print $5}'`  
echo "每秒向设备发起的写请求次数:"$disk_sda_ws  
   
# 向设备发起的I/O请求队列长度平均值  
disk_sda_avgqu_sz=`iostat -kx | grep sda| awk '{print $9}'`  
echo "向设备发起的I/O请求队列长度平均值"$disk_sda_avgqu_sz  
   
# 每次向设备发起的I/O请求平均时间  
disk_sda_await=`iostat -kx | grep sda| awk '{print $10}'`  
echo "每次向设备发起的I/O请求平均时间:"$disk_sda_await  
   
# 向设备发起的I/O服务时间均值  
disk_sda_svctm=`iostat -kx | grep sda| awk '{print $11}'`  
echo "向设备发起的I/O服务时间均值:"$disk_sda_svctm  
   
# 向设备发起I/O请求的CPU时间百分占比  
disk_sda_util=`iostat -kx | grep sda| awk '{print $12}'`  
echo "向设备发起I/O请求的CPU时间百分占比:"$disk_sda_util  

这篇文章脚本部分参考于博客:波波说运维

完结撒花!

Last modification:May 27th, 2021 at 10:35 am