shell
1. 基础
# shell的执行方式:
- 路径方式 :必须赋予权限
- source 立即执行,不需要权限
- bash 执行
新建一个文件,扩展名为sh(sh代表shell),输入一些代码:
#!/bin/bash
echo "Hello World !"
“#!” 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell。
运行Shell脚本有两种方法。
1.作为可执行程序,将上面的代码保存为test.sh,并 cd 到相应目录:
chmod +x ./test.sh #使脚本具有执行权限
./test.sh #执行脚本
注意,一定要写成./test.sh,而不是test.sh。
2.作为解释器参数,这种运行方式是,直接运行解释器,其参数就是shell脚本的文件名,如:
/bin/sh test.sh
/bin/php test.php
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
下面的脚本使用 read 命令从 stdin 获取输入并赋值给 PERSON变量,最后在 stdout 上输出:
#!/bin/bash
echo "What is your name?"
read PERSON
echo "Hello, $PERSON"
运行脚本:
chmod +x ./test.sh
$./test.sh
# 配置只使用名称运行
export PATH=/opt/sahre:$PATH #在PATH中添加目录/opt/share
export PATH=$PATH:/opt/share
export设置环境变量是暂时的,只在本次登录中有效,可修改如下文件来使命令长久有效。
1. 修改profile文件
#vi /etc/profile
在里面加入:
export PATH="$PATH:/opt/share"
这个在我们的机器上是大家共用的,建议不修改这个,只修改自己根路径下的。
2. 修改本id根路径下的.bashrc或.bash_profile或$HOME/.profile文件:
# vi /home/zhaodw/.bash_profile
在里面加入:
export PATH="$PATH:/opt/share"
source /home/zhaodw/.bash_profile
注意:
1、执行脚本时是在一个子shell环境运行的,脚本执行完后该子shell自动退出;
2、一个shell中的系统环境变量才会被复制到子shell中(用export定义的变量);
3、一个shell中的系统环境变量只对该shell或者它的子shell有效,该shell结束时变量消失(并不能返回到父shell中)。
4、不用export定义的变量只对该shell有效,对子shell也是无效的。
2. test语句
执行条件表达式
# 执行条件表达式并显示返回值。
[root@pc root]$ test ! "abc" == 123; echo $?
0
# 等价形式,注意:方括号 [ 后面的空格以及方括号 ] 前面的空格。
[root@pc root]$ [ ! "abc" == 123 ]; echo $?
0
# 支持正则的测试 [[ ]]
[root@pc root]$ [[ ! "abc" == 123 ]]; echo $?
0
3. shell 语法
算符 | 描述 | 示例 |
---|---|---|
文件比较运算符 | ||
-e filename | 如果 filename 存在,则为真 | [ -e /var/log/syslog ] |
-d filename | 如果 filename 为目录,则为真 | [ -d /tmp/mydir ] |
-f filename | 如果 filename 为常规文件,则为真 | [ -f /usr/bin/grep ] |
-L filename | 如果 filename 为符号链接,则为真 | [ -L /usr/bin/grep ] |
-r filename | 如果 filename 可读,则为真 | [ -r /var/log/syslog ] |
-w filename | 如果 filename 可写,则为真 | [ -w /var/mytmp.txt ] |
-x filename | 如果 filename 可执行,则为真 | [ -L /usr/bin/grep ] |
filename1 -nt filename2 | 如果 filename1 比 filename2 新,则为真 | [ /tmp/install/etc/services -nt /etc/services ] |
filename1 -ot filename2 | 如果 filename1 比 filename2 旧,则为真 | [ /boot/bzImage -ot arch/i386/boot/bzImage ] |
字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法) | ||
-z string | 如果 string 长度为零,则为真 | [ -z “$myvar” ] |
-n string | 如果 string 长度非零,则为真 | [ -n “$myvar” ] |
string1 = string2 | 如果 string1 与 string2 相同,则为真 | [ “$myvar” = “one two three” ] |
string1 != string2 | 如果 string1 与 string2 不同,则为真 | [ “$myvar” != “one two three” ] |
算术比较运算符 | ||
num1 -eq num2 | 等于 | [ 3 -eq $mynum ] |
num1 -ne num2 | 不等于 | [ 3 -ne $mynum ] |
num1 -lt num2 | 小于 | [ 3 -lt $mynum ] |
num1 -le num2 | 小于或等于 | [ 3 -le $mynum ] |
num1 -gt num2 | 大于 | [ 3 -gt $mynum ] |
num1 -ge num2 | 大于或等于 | [ 3 -ge $mynum ] |
#!/bin/bash
touch hello.txt
# 变量类型默认都是字符串类型,无法直接进行数值运算
echo "脚本主题: data本身就是复数" >> hello.txt
echo "========================= 特殊变量 $n $# $* $@ ========================="
echo "$HOME"
echo "$SHELL"
echo "$USER"
# $1 获取第一个参数,$2 获取第二个参数
echo "第一个爱妃是 $1, 可谓是倾国倾城"
# $# 获取入参个数
echo "此次入宫了 $# 个妃子"
# $* 代表所有参数,看作整体
echo "妃子名单*: $*"
# $@ 代表所有参数,区分对待
# shellcheck disable=SC2145
echo "妃子名单@: $@"
# $? 上一次命令的执行状态。0: 正确执行; 非0 : 执行发生错误(具体是哪个数,由命令自己决定)
echo " 上一次命令执行状态: $? "
echo "========================= 定义变量(随用随注销) ========================="
echo "A=1, 等号两边不能有空格"
echo "变量名可以由字母、数字和下划线组成,但是不能以数字开头"
echo "变量默认都是以字符串类型,无法直接进行数值运算"
echo "变量的值如果有空格,需要使用双引号或单引号括起来"
Z=1
echo "$A的值是: $Z"
echo "========================= 运算符 ========================="
echo "一共有三种方式,推荐使用$((运算符形式))"
echo " 1. $((8 + 8 * 8))"
# shellcheck disable=SC2007
echo " 2. $[8 + 8 * 8]"
# expr
echo " 3. expr 8 + 8 * 8"
echo "注意: 和声明变量不同,expr运算符间要有空格, 乘号还要转义 /*, 而且还不能运算两个以上的数字"
echo "========================= if条件判断 ========================="
echo "基本语法 [ condition ] (注意 condition 前后要有空格)"
echo "注意: condition可以是字符串: 条件非空即为true, [ wyf ] 返回true, [] 返回false"
echo " 也可以是条件表达式"
echo "注意: 在命令行中可以查询$?, 为0,代表是true, 但是在sh脚本中不管是执行了true和false分支,都是0"
echo "========================= (1) 字符串比较 ========================="
echo "= 字符串比较"
# shellcheck disable=SC2034
str="hello"
if [ "$str" ]; then
echo "true: 字符串{$str}不为空"
else
echo "false: 字符串{$str}为空"
fi
echo "========================= (2) 两个整数之间的比较 ==================="
echo "-lt 小于(less than) -le 小于等于(less equal)"
echo "-eq 等于(equal) -ne 不等于(not equal) "
echo "-gt 大于(greater than) -ge 大于等于(greater equal)"
# shellcheck disable=SC2050
if [ 23 -ge 22 ]; then
echo "true: 23 >= 22"
else
echo "false: 23 < 22"
fi
echo "========================= (3) 按照文件权限进行判断 ==================="
echo "-r 有读的权限(read)"
echo "-w 有写的权限(write)"
echo "-x 有执行的权限(execute)"
echo "========================= (4) 按照文件类型进行判断 ==================="
echo "-e 文件存在(exist)"
echo "-f 文件存在并且是一个常规的文件(file)"
echo "-d 文件存在并且是一个目录(directory)"
if [ -d hello.sh ]; then
echo "true: hello.sh 是directory"
else
echo "false: hello.sh 不是directory"
fi
echo "========================= 流程控制(重点) ==================="
echo "========================= (1) if判断 ==================="
echo "基本语法: if 后要有空格和fi闭环"
echo "if [ condition ]; then"
echo " true分支 "
echo "fi"
echo "====== elif 和 else ======"
echo "
if [ condition ]; then
commands;
elif [ condition ]; then
commands;
else
commands;
fi"
echo "========================== (2) case语句 ========================"
# shellcheck disable=SC2162
# read -p "please input a number to case statement:" num #打印信息提示用户输入,输入信息赋值给num变量
num=3
case "$num" in
1)
echo "The num you input is 1"
;;
[2-5])
echo "The num you input is 2-5"
;;
[6-9])
echo "The num you input is 6-9"
;;
*)
echo "please input number[1-9] int"
esac
echo "========================== (3) for循环 ========================"
sum=0
for ((i = 1; i <= 100; i++))
do
sum=$((sum + i))
done
echo "1~100的累加和: $sum"
echo "遍历输入参数: "
for p in "$@"
do
echo "爱妃: $p"
done
sum2=0
k=1
while [ $k -le 50 ]
do
sum2=$((sum2 + k))
k=$((k + 1))
done
echo "1~50的累加和: $sum2"
#echo "========================== (3) read读取控制台输入 ========================"
#read -r -p "请输入你喜欢的演员, -r可以正常读取反斜杠: " girlName
#echo "$girlName 是你的女朋友"
#read -r -t 3 -p "请在三秒内输入另一个女明星: " other
#
#if [ "$other" ]; then
# echo "$other 也是你的女朋友"
#else
# echo "我就知道你很专一"
#fi
echo "========================== 系统函数 ========================"
echo "========================== (1) basename ========================"
# 基本语法: basename NAME [SUFFIX]
# 删除前导目录, 打印名称
# 如果指定,还可以删除后缀
# $(cmd) 指定输出
fileNameWithSuffix=$(basename include/stdio.h)
echo "$fileNameWithSuffix" # stdio.h
fileName=$(basename include/stdio.h .h)
echo "$fileName" # stdio
echo "========================== (2) dirname ========================"
# Usage: dirname [OPTION] NAME...
# 输出 Name的所在最后一个斜杠之前的内容(NAME所在目录部分,且删除最后一个斜杠)
# 如果Name不包含斜杆,则输入 '.' ,代表当前目录
dir1=$(dirname /usr/bin/)
dir2=$(dirname /AuI18N/2052/usr/bin/a.txt)
dir3=$(dirname stdio.h)
echo "dir1: $dir1"
echo "dir2: $dir2"
echo "dir3: $dir3"
echo "========================== 自定义函数 ========================"
echo "标准写法: "
function name() {
echo "== name() =="
return 0
# [return value], value取值范围是0-255
# 表示函数的返回值,可写可不写
}
name
# 函数返回值只能通过$?系统变量获得,可以显示加。如果不加,讲以最后一条命令运行结果做回返回值
echo "func result : $?"
function twoSum() {
s=0
s=$(($1+$2))
echo "twoSum result : $s"
}
# 调用 Shell 函数时可以给它传递参数,也可以不传递
# 如果不传递参数,直接给出函数名字即可:name
# 如果传递参数,那么多个参数之间以空格分隔:name param1 param2 param3
twoSum 6 6
echo "========================== sed ========================"
echo "Usage: sed [选项] 'command' fileName"
echo " -n, --quiet, --silent 只打印匹配行"
echo "也可以用数字开头,代表对指定行操作"
echo " 常用命令: s替换 d删除 p打印 q退出 i行前 a行后"
echo "-e 和 ; 都可以实现多条cmd"
#sed "s/u/UC/g" abc.txt # u ==> UC, g代表整行都替换
#echo "=="
#sed "s/u/UC/" abc.txt
# sed "s/a//g" abc.txt # 把所有的a都删掉了
# sed "s/#.*//g" abc.txt # -i 会对源文件进行修改
# sed "s/\s*#.*//g" abc.txt # \s*代表0或多个空格
# sed "s/\s*#.*//g; /^$/d" abc.txt # /^$/d删除空行
# sed "/a/q" abc.txt # 遇到第一个a就退出
# sed -n "/a/p" abc.txt # 打印匹配到a的行
# sed "3q" abc.txt # 打印到第三行就退出
# sed "3p" abc.txt # 到第三行就打印
#sed "/^wo/a cao" abc.txt # a 在匹配行后加一行
#sed "/^wo/i ai~" abc.txt # i 在匹配行前加一行
#cmd1="2a mei nv22"
#sed "$cmd1" abc.txt
#sed "3s/a/TT/g" abc.txt # 只给第三行的a换成了TT
#sed "/lai/d" abc.txt
#sed "4d;s/wo/ni/g" abc.txt # ; 号实现多条命令,删除第四行,且替换字符
#sed -e "4d" -e "s/wo/ni/g" abc.txt # ; 号实现多条命令,删除第四行,且替换字符
echo "============================== awk ============================="
echo "常用函数:
tolower():字符转为小写。
length():返回字符串长度。
substr():返回子字符串。
rand():随机数。
"
echo "一个强大的文本分析工具,把文件逐行读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理"
echo "awk [选项参数] 'pattern1{action1} pattern2{action2}...'" fileName
echo "pattern : 表示awk在数据中查找的内容"
echo "action : 在找到所匹配内容时所执行的一系列命令"
echo "常用选项参数 -F 指定分隔符"
echo "常用选项参数 -v 定义变量, awk的变量是与世隔绝的,里面取不到外面的,外面的也取不到里面的"
awk -F ":" '/^root/ {print $7}' demo.txt
awk -F ":" '/^root/ {print $1 ", " $7}' demo.txt
awk -F ":" '/^root/ {printf("第一列内容是%s, 第7列内容是: %s ! \n", $1, $7)}' demo.txt
# BEGIN 和 END
awk -F ":" 'BEGIN{print "=== lu ben wei niu bi~ ==="}
/^root/ {printf("第一列内容是%s, 第7列内容是: %s ! \n", $1, $7)}
END{print "=== bi xv di ! ==="}' demo.txt
awk -F ":" 'BEGIN{print "=== lu ben wei niu bi~ ==="}
{printf("第一列内容是%s, 第7列内容是: %s ! \n", $1, $7)}
END{print "=== bi xv di ! ==="}' demo.txt
awk -F ":" -v i=1 '{print $3 + i}' demo.txt # 定义变量,给第三列加1
# awk 内置变量
awk -F ":" '{printf("文件名: %s, 行号: %s, 该行一共 %s 列, 第一列: %s \n", FILENAME, NR, NF, $1)}' demo.txt
# 打印空行的行号
awk '/^$/ {printf("空行行号: %s \n", NR)}' demo.txt
echo "================== wc ================="
echo "Usage: wc [OPTION]... [FILE]..."
echo "wc 会把文件名称打印出来,可以用awk去除"
total_lines=$(wc -l demo.txt | awk -F " " '{print $1}')
total_bytes=$(wc -c demo.txt | awk -F " " '{print $1}')
echo "demo.txt ==>> 总行数: $total_lines, 总字节数: $total_bytes"
echo "================ sort =================="
echo "Usage: sort [OPTION]... [FILE]..."
echo "
-n, 按照数值排序
-r, 反序
-b, 忽略前导空格
-t, 指定排序时所用的栏位分隔字符
-k, 指定排序的列
"
echo "按照日排序(第三列)"
sort -t "-" -k 3 -n sort.txt
sort -t "-" -k 3 -n -r sort.txt
4. 实操
1. 基础
# 利用for循环建立user1~~user5总共五个账号,并且密码均为redhat
# 提示man passwd命令中以标准输入方式给予账号密码。
vim user.sh
#!/bin/bash
for i in {1..5}
do
useradd user$i
echo redhat | passwd --stdin user$i
done
sh user.sh
# 访问网页
#!/bin/bash
url=http://127.0.0.1
code=$(curl -s -I -m 2 -o /dev/null $url -w %{http_code})
if [ "$code" -eq 200 ]; then
echo "page is ok"
else
echo "404"
fi
# 输入输出
#!/bin/bash
echo "输入用户名: "
#读取从键盘的输入
read username
id $username &> /dev/null
if [ $? -eq 0 ] ; then
echo "user exists"
else
useradd ${username}
fi
# case
#!/bin/bash
case $1 in
a|A)
echo a;;
b|B)
echo b;;
*)
echo none;;
esac
# 测试ping
#!/bin/bash
for i in {1..20}
do
ping -c 5192.168.70.$i &> /dev/null
if [ $? -eq 0 ];then
echo "192.168.70.$i is up"
else
echo "192.168.70.$i is down"
fi
done
# 九九乘法表
#!/bin/bash
for((i=1;i<=9;i++))
do
for((j=1;j<=i;j++))
do
echo -n "${j}x${i}=$[i*j] "
done
echo
done
# 控制台给函数传参
#!/bin/bash
#test()
{
echo "$1 and $2"
}
#test 1 2
2. 常见问题
#!/bin/bash
# 计算demo.txt第三列总和
third_sum=$(awk -F ":" -v sum=0 '{sum+=$3} END{print sum}' demo.txt)
echo "第三列的和是: $third_sum"
unset third_sum
# 判断一个文件是否存在
if [ -f sort.txt ]; then
echo "sort.txt 文件存在"
else
echo "sort.txt 文件不存在"
fi
# 在当前目录查找包含字符 shen 的文件名称
# uniq 去重
# uniq 在后面显示行重复次数
grep -r shen | awk -F ":" '{print $1}' | uniq -c
# 输出 0 ~ 500 之间7的倍数
#for ((i = 0; i <= 500; i++))
#do
# if [ $((i % 7)) -eq 0 ]; then
# echo "$i"
# fi
#done
#unset "$i"
#exit 0
#for i in {0..500}
#do
# if [ $((i % 7)) -eq 0 ]; then
# echo "$i"
# fi
#done
#unset "$i"
#exit 0
# 生成 0 ~ 500的数字, 步长为7
# seq 0 7 500
# 写一个 bash脚本以统计一个文本文件 nowcoder.txt中字母数小于8的单词。
#
#
#
#示例:
#假设 nowcoder.txt 内容如下:
#how they are implemented and applied in computer
#
#你的脚本应当输出:
#how
#they
#are
#and
#applied
#in
awk '{
for (i=1; i <= NF; i++) {
if (length($i) < 8){
print $i
}
}
}' n.txt
# 打印出空行,或者只有空格和制表符的行
awk 'NF == 0 {print NR}' n.txt
# 统计每个单词出现的次数
echo "===!!@@====="
awk '{
for (i=1; i <= NF; i++) {
print $i
}
}' now.txt | sort | uniq -c | awk '{printf("%s %s\n", $2, $1)}' | sort -k 2 -n > res.txt
echo "====="
awk '{
for (i = 1; i <= NF; ++i)
mp[$i]++;
}
END {
for (k in mp)
printf("%s %d\n", k, mp[k]);
}' now.txt | sort -k 1 -n
awk '{print $2}' nowcoder.txt |
sort -n |
uniq -c |
awk '$1 > 1 {print $0}'
echo "
假设每行列数相同,并且每个字段由空格分隔
示例:
假设 nowcoder.txt 内容如下:
job salary
c++ 13
java 14
php 12
你的脚本应当输出(以词频升序排列):
job c++ java php
salary 13 14 12
"
cols=$(sed "1q" nowcoder.txt | awk '{print NF}')
for ((i = 1; i <= cols; i++)); do
awk -v k="$i" '{printf("%s ", $k)}' nowcoder.txt
echo
done
echo "
写一个 bash脚本以统计一个文本文件 nowcoder.txt中每一行出现的1,2,3,4,5数字个数
并且要计算一下整个文档中一共出现了几个1,2,3,4,5数字数字总数。
示例:
假设 nowcoder.txt 内容如下:
a12b8
10ccc
2521abc
9asf
你的脚本应当输出:
line1 number: 2
line2 number: 1
line3 number: 4
line4 number: 0
sum is 7
"
awk -F "" '
BEGIN{sum = 0}
{
count = 0;
for (i = 0; i < NF; i++) {
if ($i == 1 || $i == 2 || $i == 3 || $i == 4 || $i == 5) {
count++;
}
}
sum += count;
printf("line%s number:%d\n", NR, count);
}
END{printf("sum is %d\n", sum)}
' nowcoder.txt
echo "
写一个bash脚本以实现一个需求,求输入的一个的数组的平均值
第1行为输入的数组长度N
第2~N行为数组的元素,如以下为:
数组长度为4,数组元素为1 2 9 8
示例:
4
1
2
9
8
那么平均值为:5.000(保留小数点后面3位)
你的脚本获取以上输入应当输出:
5.000
"
awk 'BEGIN{sum = 0; len = 0}
{
if (NR == 1) {
len = $1;
} else {
sum += $1;
}
}
END{printf("%0.3f\n", sum / len)}'
# xargs
应用场景1: 批量更改当前目录下的文件名
ls ./ | xargs -I GG echo "mv GG prefix_GG"
ls ./ | xargs -I GG mv GG prefix_GG
也可以这样批量更改该文件下的文件名
for i in ./*; do
name=$(basename "$i")
echo "mv $name sup_$name"
done
3. 获取硬件信息
#!/bin/bash
#CPU型号
cpu_model=`cat /proc/cpuinfo | grep "model name" | awk -F ':' '{print $2}' | sort | uniq`
echo "$cpu_model"
#CPU架构
cpu_architecture=`uname -m`
echo "$cpu_architecture"
#物理CPU个数
cpu_phy_num=`cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l`
echo "$cpu_phy_num"
#CPU核数
cpu_core_num=`cat /proc/cpuinfo | grep "cpu cores" | uniq | awk -F ': ' '{print $2}'`
echo "$cpu_core_num"
#逻辑CPU个数
cpu_proc_num=`cat /proc/cpuinfo | grep "processor" | uniq | wc -l`
echo "$cpu_proc_num"
##CPU主频
cpu_main_freq=`cat /proc/cpuinfo | grep "model name" | awk -F '@' 'NR==1 {print $2}'`
echo "$cpu_main_freq"
##L1d缓存
cpu_l1d_cache=`lscpu | grep -i 'L1d 缓存\|L1d cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l1d_cache"
##L1i缓存
cpu_l1i_cache=`lscpu | grep -i 'L1i 缓存\|L1i cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l1i_cache"
##L2缓存
cpu_l2_cache=`lscpu | grep -i 'L2 缓存\|L2 cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l2_cache"
##L3缓存
cpu_l3_cache=`lscpu | grep -i 'L3 缓存\|L3 cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l3_cache"
#操作系统名称
system_name=`head -n 1 /etc/issue | awk '{print $1,$2}'`
echo "$system_name"
#操作系统位数
systembit=`getconf LONG_BIT`
echo "$systembit"
#操作系统内核版本
system_kernel=`uname -r`
echo "$system_kernel"
#物理内存容量
meminfo=`sudo dmidecode | grep "^[[:space:]]*Size.*MB$" | uniq -c | sed 's/ \t*Size: /\*/g' | sed 's/^ *//g'`
echo "$meminfo"
#单位转换函数
function convert_unit()
{
result=$1
if [ $result -ge 1048576 ]
then
value=1048576 #1024*1024
result_gb=$(awk 'BEGIN{printf"%.2f\n",'$result' / '$value'}') #将KB转换成GB,并保留2位小数
echo $result_gb"GB"
elif [ $result -ge 1024 ]
then
value=1024
result_mb=$(awk 'BEGIN{printf"%.2f\n",'$result' / '$value'}') #将KB转换成MB,并保留2位小数
echo $result_mb"MB"
else
echo $result"KB"
fi
}
#单位:KB
MemTotal=$(cat /proc/meminfo | awk '/^MemTotal/{print $2}') #内存总量
MemFree=$(cat /proc/meminfo | awk '/^MemFree/{print $2}') #空闲内存
MemUsed=$(expr $MemTotal - $MemFree) #已用内存
##计算内存占用率
Mem_Rate=$(awk 'BEGIN{printf"%.2f\n",'$MemUsed' / '$MemTotal' *100}') #保留小数点后2位
MemShared=$(cat /proc/meminfo | awk '/^Shmem/{print $2}') #共享内存
Buffers=$(cat /proc/meminfo | awk '/^Buffers/{print $2}') #文件缓冲区
Cached=$(cat /proc/meminfo | awk '/^Cached/{print $2}') #用于高速缓冲存储器
SwapTotal=$(cat /proc/meminfo | awk '/^SwapTotal/{print $2}') #交换区总量
SwapFree=$(cat /proc/meminfo | awk '/^SwapFree/{print $2}') #空闲交换区
Mapped=$(cat /proc/meminfo | awk '/^Mapped/{print $2}') #已映射
##虚拟内存
VmallocUsed=$(cat /proc/meminfo | awk '/^VmallocUsed/{print $2}') #已使用的虚拟内存
echo "$(convert_unit $MemTotal)"
echo "$(convert_unit $MemFree)"
echo "$(convert_unit $MemUsed)"
echo "$Mem_Rate%"
echo "$(convert_unit $MemShared)"
echo "$(convert_unit $Buffers)"
echo "$(convert_unit $Cached)"
echo "$(convert_unit $SwapTotal)"
echo "$(convert_unit $SwapFree)"
echo "$(convert_unit $Mapped)"
echo "$(convert_unit $VmallocUsed)"
#磁盘型号
disk_model=`fdisk -l | grep "Disk model" | awk -F : '{print $2}' | sed 's/^ //'`
echo "$disk_model"
usesum=0
totalsum=0
disknum=`df -hlT |wc -l `
for((n=2;n<=$disknum;n++))
do
use=$(df -k |awk NR==$n'{print int($3)}')
pertotal=$(df -k |awk NR==$n'{print int($2)}')
usesum=$[$usesum+$use] #计算已使用的总量
totalsum=$[$totalsum+$pertotal] #计算总量
done
freesum=$[$totalsum-$usesum]
diskutil=$(awk 'BEGIN{printf"%.2f\n",'$usesum' / '$totalsum'*100}')
freeutil=$(awk 'BEGIN{printf"%.2f\n",100 - '$diskutil'}')
#磁盘总量
if [ $totalsum -ge 0 -a $totalsum -lt 1024 ];then
echo "$totalsum K"
elif [ $totalsum -gt 1024 -a $totalsum -lt 1048576 ];then
totalsum=$(awk 'BEGIN{printf"%.2f\n",'$totalsum' / 1024}')
echo "$totalsum M"
elif [ $totalsum -gt 1048576 ];then
totalsum=$(awk 'BEGIN{printf"%.2f\n",'$totalsum' / 1048576}')
echo "$totalsum G"
fi
#磁盘已使用总量
if [ $usesum -ge 0 -a $usesum -lt 1024 ];then
echo "$usesum K"
elif [ $usesum -gt 1024 -a $usesum -lt 1048576 ];then
usesum=$(awk 'BEGIN{printf"%.2f\n",'$usesum' / 1024}')
echo "$usesum M"
elif [ $usesum -gt 1048576 ];then
usesum=$(awk 'BEGIN{printf"%.2f\n",'$usesum' / 1048576}')
echo "$usesum G"
fi
#磁盘未使用总量
if [ $freesum -ge 0 -a $freesum -lt 1024 ];then
echo "$freesum K"
elif [ $freesum -gt 1024 -a $freesum -lt 1048576 ];then
freesum=$(awk 'BEGIN{printf"%.2f\n",'$freesum' / 1024}')
echo "$freesum M"
elif [ $freesum -gt 1048576 ];then
freesum=$(awk 'BEGIN{printf"%.2f\n",'$freesum' / 1048576}')
echo "$freesum G"
fi
#磁盘占用率
echo "$diskutil%"
#磁盘空闲率
echo "$freeutil%"
#显卡型号
graphicscardmodel=`lspci | grep -i 'VGA' | sed '2d' | cut -f3 -d ":" | sed 's/([^>]*)//g'`
echo "$graphicscardmodel"
#显卡生产商
graphicscardmanufacturer=`lspci | grep -i 'VGA'| sed '2d'| awk '{ print $5,$6 }'`
echo "$graphicscardmanufacturer"
#主板厂商
boardmanufacturer=`sudo dmidecode | grep -A 10 "Base Board Information" |grep "Manufacturer" | awk -F ':' '{print $2}'`
echo "$boardmanufacturer"
#主板名称
boardname=`sudo dmidecode | grep -A 10 "Base Board Information" |grep "Product Name" | awk -F ':' '{print $2}'`
echo "$boardname"
#BIOS厂商
biosvendor=`sudo dmidecode | grep -A 28 "BIOS Information" | grep 'Vendor' | awk -F ':' '{print $2}'`
echo "$biosvendor"
#BIOS版本
biosversion=`sudo dmidecode | grep -A 28 "BIOS Information" | grep 'Version' | awk -F ':' '{print $2}'`
echo "$biosversion"
#BIOS发行日期
biosrelease=`sudo dmidecode | grep -A 28 "BIOS Information" | grep 'Release' | awk -F ':' '{print $2}'`
echo "$biosrelease"
#网卡信息
netcardinfo=`lspci | grep -i eth | head -n +1 | awk -F : '{print $3}' | sed 's/^ //'`
echo "$netcardinfo"
4. 获取硬件使用率
#!/bin/bash
# 获取要监控的本地服务器IP地址
IP=`ifconfig | grep inet | grep -vE 'inet6|127.0.0.1' | awk '{print $2}'`
echo "IP地址:"$IP
# 获取cpu总核数
cpu_num=`grep -c "model name" /proc/cpuinfo`
echo "cpu总核数:"$cpu_num
# 1、获取CPU利用率
################################################
#us 用户空间占用CPU百分比
#sy 内核空间占用CPU百分比
#ni 用户进程空间内改变过优先级的进程占用CPU百分比
#id 空闲CPU百分比
#wa 等待输入输出的CPU时间百分比
#hi 硬件中断
#si 软件中断
#################################################
# 获取用户空间占用CPU百分比
cpu_user=`top -b -n 1 | grep Cpu | awk '{print $2}' | cut -f 1 -d "%"`
echo "用户空间占用CPU百分比:"$cpu_user
# 获取内核空间占用CPU百分比
cpu_system=`top -b -n 1 | grep Cpu | awk '{print $4}' | cut -f 1 -d "%"`
echo "内核空间占用CPU百分比:"$cpu_system
# 获取空闲CPU百分比
cpu_idle=`top -b -n 1 | grep Cpu | awk '{print $8}' | cut -f 1 -d "%"`
echo "空闲CPU百分比:"$cpu_idle
# 获取等待输入输出占CPU百分比
cpu_iowait=`top -b -n 1 | grep Cpu | awk '{print $10}' | cut -f 1 -d "%"`
echo "等待输入输出占CPU百分比:"$cpu_iowait
#2、获取CPU上下文切换和中断次数
# 获取CPU中断次数
cpu_interrupt=`vmstat -n 1 1 | sed -n 3p | awk '{print $11}'`
echo "CPU中断次数:"$cpu_interrupt
# 获取CPU上下文切换次数
cpu_context_switch=`vmstat -n 1 1 | sed -n 3p | awk '{print $12}'`
echo "CPU上下文切换次数:"$cpu_context_switch
#3、获取CPU负载信息
# 获取CPU15分钟前到现在的负载平均值
cpu_load_15min=`uptime | awk '{print $11}' | cut -f 1 -d ','`
echo "CPU 15分钟前到现在的负载平均值:"$cpu_load_15min
# 获取CPU5分钟前到现在的负载平均值
cpu_load_5min=`uptime | awk '{print $10}' | cut -f 1 -d ','`
echo "CPU 5分钟前到现在的负载平均值:"$cpu_load_5min
# 获取CPU1分钟前到现在的负载平均值
cpu_load_1min=`uptime | awk '{print $9}' | 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
#4、获取内存信息
# 获取物理内存总量
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 "剩余内存总量(操作系统):"$mem_sys_free
# 获取应用程序已使用的内存总量
mem_user_used=`free | sed -n 3p | awk '{print $3}'`
echo "已使用内存总量(应用程序):"$mem_user_used
# 获取应用程序未使用内存总量
mem_user_free=`free | sed -n 3p | awk '{print $4}'`
echo "剩余内存总量(应用程序):"$mem_user_free
# 获取交换分区总大小
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
#5、获取磁盘I/O统计信息
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
5. 密码比对
#!/bin/bash
COUNT=0
PASSWD=12345
while [ $COUNT -lt 3 ]
do
read -p "input passwd:" password
if [ "$password" = "$PASSWD" ];then
echo "right"
exit
else
echo "wrong"
let COUNT++
fi
done
echo "too many wrong!"
6. 磁盘监控
df -hl 查看磁盘剩余空间
df -h 查看每个根路径的分区大小
du -sh [目录名] 返回该目录的大小
du -sm [文件夹] 返回该文件夹总M数
du -h [目录名] 查看指定文件夹下的所有文件大小(包含子文件夹)
查看硬盘的分区 #sudo fdisk -l
查看IDE硬盘信息 #sudo hdparm -i /dev/hda
查看STAT硬盘信息 #sudo hdparm -I /dev/sda 或 #sudo apt-get install blktool #sudo blktool /dev/sda id
查看硬盘剩余空间 #df -h #df -H
查看目录占用空间 #du -hs 目录名
使用命令查看指定目录空间情况,例如查看opt目录
du -h --max-depth=1 /opt
#!/bin/bash
echo "磁盘当前实时读写速率:"
# 每秒向设备发起的读请求次数
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
max_filesys_use=`df -h | sort -nr -k5 | head -n1`
echo "最大文件系统使用率:"
echo $max_filesys_use
echo "磁盘使用情况:"
df -h | grep "/dev/sda"
disk_use=`df -h | grep "/dev/sda" | awk '{print $5}' | cut -d '%' -f 1`
echo "磁盘使用率: $disk_use%"
echo "inode监控:"
df -i
文章来源地址https://www.toymoban.com/news/detail-448762.html
文章来源:https://www.toymoban.com/news/detail-448762.html
到了这里,关于linux shell脚本详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!