linux练手小项目:探测系统信息
看了b站上的一个教学视频,复习了一下拿取 linux 系统信息的方法,并跟着up写了一个小的脚本完成一系列需求。写一篇博文记录一下这个过程,以后回顾用。
需求
- 显示当前运行的操作系统的名称版本
- 显示当前系统的 CPU 信息:核心数量,生产厂商, CPU 型号
- 显示当前系统的内存信息:内存总数,使用数量,空闲数量
- 显示当前系统的磁盘信息,包括分区情况
- 能兼容如下操作系统:
- Ubuntu 22.04 -Y Pl
- Rock Linux (Redhat/Centos) 8.x -5 Pl
- Rock Linux (Redhat/Centos) 9.x Pl
过程要点
- 检测兼容性:
- 方法一:找
/etc
目录下的xxx-release
文件,里面放着系统名称版本信息。这一方法需要先去确定需要兼容的系统的文件所处位置。 - 方法二: 利用用于展示开机欢迎信息的
/etc/issue
文件;如本机中该文件内容为Ubuntu 20.04.6 LTS \n \l
,解释见博文:/etc/issue,也可以在 man issue 文档中找到。 - 方法三:使用
lsb_release
命令用来看当前 linux 系统的名称版本,但缺少该工具时需要使用方法一二兜底。
- 方法一:找
- 各个需求需要用到的获取信息方法已在上一篇文章记录:linux系统监控命令小记
- 注意学习正则表达式的使用,在处理信息时使用 ”
sed
+ 正则“ 的组合很有用。 多翻阅 man 文档!中文的可以看前辈博文:shell脚本之sed详解 - 在写脚本时,为了方便维护,将每个需要实现的需求用函数分开。如使用
cpu_info()
、memory_info()
、disk_info()
等等。 - 在构思脚本运行的逻辑时,像平时编写程序那样思考:从
main()
出发;遇到类似 switch 的逻辑时将其单独划分开成为一个函数,如用于处理脚本参数的parse_args()
。 - 处理 switch 逻辑时使用的
getopts
语法:Linux 命令行参数解析工具 getopts - 黄大仙的文章 - 知乎 - shell 脚本中处理错误返回时注意设置返回值为 非零值.
- 记得写上你脚本的
-h
选项处理!给出你脚本使用的方法!
遇到的坑
使用 echo
时,不带引号会自动将多余的空格去掉,从而导致 grep
的匹配出错:
njucs@Ubuntu20:~/project/lsbs$ cat /proc/cpuinfo | grep "model name" | uniq
model name : 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
njucs@Ubuntu20:~/project/lsbs$ suki=$(cat /proc/cpuinfo | grep "model name" | uniq)
njucs@Ubuntu20:~/project/lsbs$ echo $suki
model name : 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
njucs@Ubuntu20:~/project/lsbs$ echo "$suki"
model name : 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
源码展示
一共200行不到,主要是熟悉探测信息工具的使用。
#!/usr/bin/env bash
# ATTENTION: compatibility needed !!!
distro_name=''
kernel_version=''
function check_yum_based_distro() {
echo "Waiting for you to perfect."
exit 1
# # echo "check yum/dnf based distro"
# # [root@rock8 lsbs]# cat /etc/rocky-release
# # Rocky Linux release 8.9 (Green Obsidian)
# if [ -f /etc/rocky-release ]; then
# distro="RockyLinux"
# version="$(sed -E 's#.*([0-9].[0-9]).*#\1#g' /etc/rocky-release)"
# return;
# fi
# # [root@rock8 lsbs]# cat /etc/centos-release
# # Rocky Linux release 8.9 (Green Obsidian)
# if [ -f /etc/centos-release ]; then
# distro="Centos"
# version="$(sed -E 's#.*([0-9].[0-9]).*#\1#g' /etc/redhat-release)"
# return
# fi
# if [ -f /etc/redhat-release ]; then
# distro="RHEL"
# version="$(sed -E 's#.*([0-9].[0-9]).*#\1#g' /etc/redhat-release)"
# return
# fi
}
function check_apt_based_distro() {
# njucs@Ubuntu20:~$ cat /etc/issue
# Ubuntu 20.04.6 LTS \n \l
if [[ -f /etc/issue ]]; then
# Ubuntu xx.yy.zz LTS
sed -E 's/^(Ubuntu) ([0-9\.]*) ((LTS)?) (.*)$/\1 \2 \3/' /etc/issue | read distro_name
return
fi
}
function distro_info() {
# 检查lsb_release命令是否存在
local is_exist_lsb_release=0
which lsb_release > /dev/null 2>&1
is_exist_lsb_release=$?
if [[ $is_exist_lsb_release -eq 0 ]]; then
distro_name=$(lsb_release -ds)
else
echo "WARNING: lsb_release command not found. "
# 检查当前操作系统是否基于yum包管理器
if which yum > /dev/null 2>&1; then
check_yum_based_distroj
return
# 检查当前操作系统是否基于apt包管理器
elif which apt > /dev/null 2>&1; then
check_apt_based_distro
return
else
echo "ERROR: Unsupported operating system, exit... "
exit 1
fi
fi
if [[ -z "$distro_name" ]]; then
echo "ERROR: Failed to get distro name, exit..."
exit 1
fi
}
function kernel_info() {
# 获取内核信息
kernel_version=$(uname -r)
}
function system_info() {
# 获取系统信息
distro_info
kernel_info
# 其他系统信息...
echo "----------------SYSTEM INFO------------------------"
echo "OS Distro: ${distro_name}"
echo "Kernel version: ${kernel_version}"
}
function cpu_info() {
# 获取CPU信息
cpu_cores_numb=$(cat /proc/cpuinfo | grep "cpu cores" | uniq | cut -f 3 -d ' ')
cpu_cores_vendor=$(cat /proc/cpuinfo | grep "vendor_id" | uniq | cut -d ' ' -f 2)
cpu_cores_model=$(echo `cat /proc/cpuinfo | grep "model name" | uniq` | awk '{sub("model name : ","");print}')
echo "------------------CPU INFO------------------------"
echo "The CPU cores' number : ${cpu_cores_numb}"
echo "The CPU vendor : ${cpu_cores_vendor}"
echo "The CPU model : ${cpu_cores_model}"
}
function memory_info() {
# 获取内存信息
mem_total=$(free -m | grep Mem | awk '{print $2}')
mem_used=$(free -m | grep Mem | awk '{print $3}')
mem_free=$(free -m | grep Mem | awk '{print $4}')
echo "-------------------MEMORY-------------------------"
echo "The total memory : ${mem_total} MB"
echo "The used memory : ${mem_used} MB"
echo "The free memory : ${mem_free} MB"
}
function disk_info() {
echo "------------------DISK INFO------------------------"
# 获取磁盘信息
lsblk -o 'NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE' | grep -vE "sr0|loop*"
}
checkcpu=0
checkmem=0
checkdisk=0
summary=0
# system_detect.sh -s | [-c | -m | -d] | -h
function usage() {
echo -e "System information summary tool.\n"
echo -e "Usage:\n $(basename $0) [-h] [-s] [-c | -m | -d]\n"
echo "Options:"
echo " -h Show help"
echo " -s Get summary"
echo " -c Get CPU info"
echo " -m Get memory info"
echo " -d Get disk info"
}
function parse_args() {
while getopts ":scmdh" opt; do
case ${opt} in
h)
usage
;;
s)
summary=1
;;
c)
checkcpu=1
;;
m)
checkmem=1
;;
d)
checkdisk=1
;;
\?)
echo "Invalid option: -$OPTARG"
usage
exit 1
;;
esac
done
if [[ $OPTIND -eq 1 ]]; then
echo "No options provided. Please provide -h for help."
exit 1
fi
}
function main() {
parse_args "$@"
system_info
if [[ $summary -eq 1 ]]; then
cpu_info
memory_info
disk_info
exit 0
else
if [[ $checkcpu -eq 1 ]]; then
cpu_info
fi
if [[ $checkmem -eq 1 ]]; then
memory_info
fi
if [[ $checkdisk -eq 1 ]]; then
disk_info
fi
exit 0
fi
}
### !!! main starts here !!! ###
main "$@"