本文介绍了Shell脚本编程的基础知识,包括Shell语言特点、文件结构、变量定义与引用、脚本调用方式等核心内容。
重点讲解了条件判断(if语句)和循环结构(for/while循环)的语法与应用场景,并提供了多个实用示例,如磁盘容量监控、文件备份、日志巡检等。
文章还涉及Shell脚本参数传递和常见面试问题,适合初学者快速掌握Shell脚本编程基础。
通过具体案例展示了Shell在Linux环境下的自动化运维能力。
Shell 笔记
Shell 简介
Shell 是一门编程语言。
编程语言示例:
Java、Python、C++、C#、Php、Shell ....
特点:
-
基于 Linux 环境,可以原生运行的一个脚本语言
-
开发出来的脚本文件,一般是以
.sh结尾的可执行文件
| 文件后缀 | 文件类型 |
|---|---|
| xxx.sh | Shell 脚本 |
| xxx.py | Python 脚本 |
| xxx.jar | Jar 包 |
Shell 脚本文件结构
bash
#!/bin/bash # 或者 #!/bin/sh —— 头文件,用于定义编译器
# 逻辑体
1. 变量
a. 定义变量
基本格式: 变量名=变量值 (左右两边不允许出现空格)
bash
A=10 # 定义变量A的值是10
B="hello world"
使用Linux命令赋值: 变量名=$(Linux命令)
bash
C=$(cat emp | wc -l)
b. 引用变量
格式: $变量名
bash
echo $A
echo $B
echo $C
echo $A"$B" # 当变量需要跟其他内容拼接字符串时,需要双引号
2. 调用 Shell 脚本
a. 用 sh 调用
bash
sh task.sh
sh /home/hadoop/2608/test/task.sh
b. 用 ./shell脚本 调用
前置条件:
-
必须在脚本的父目录
-
调用该脚本的用户必须要有执行权限
示例脚本
示例1:打印当前服务器磁盘剩余容量
bash
#!/bin/bash
free=$(df -h | awk -F " " '{print $4}' | sed -n '6p')
echo "当前磁盘剩余:"$free
示例2:打印变量A + 20 的返回值
bash
#!/bin/bash
D=$(($A + 20))
echo "变量A+20的结果是:"$D
练习1
开发 Shell 脚本,统计 Linux 的两块内存的总剩余容量。
3. 场景判断(if语句)
语法结构
bash
if 判断条件
then
要做的事情
elif 判断条件
then
要做的事情
else
要做的事情
fi
a. 判断条件注意事项
-
[ 比较值1 比较符号 比较值2 ]------ 空格不能少 -
比较符:
| 比较符 | 含义 |
|---|---|
== 或 -eq |
等于 |
-gt |
大于(greater than) |
-lt |
小于(less than) |
-ge |
大于等于(greater equal) |
-le |
小于等于(less equal) |
-ne |
不等于(not equal) |
示例:统计文件个数
bash
# 开发shell脚本统计 /home/hadoop/2608 下面的文件个数
# 如果大于10个则打印"文件很多"
# 如果大于5个则打印"文件正常"
# 否则打印"文件过少"
file_num=$(find /home/hadoop/2608 -type f | wc -l)
if [ $file_num -gt 10 ]
then
echo "文件很多"
elif [ $file_num -gt 5 ]
then
echo "文件正常"
else
echo "文件过少"
fi
4. 循环
1. for循环
语法:
bash
for((i=1;i<=100;i++))
{
循环要做的事情 # $i
}
示例1:1~100求和
bash
sum=0
for((i=1;i<=100;i++))
{
sum=$[$sum + $i]
}
echo $sum
示例2:删除目录下所有文件
bash
total_num=$(find /home/hadoop/2608 -type f | wc -l)
for((i=1;i<=$total_num;i++))
{
file_name=$(find /home/hadoop/2608 -type f | grep -v "task" | head -$i | tail -1)
rm -rf $file_name
}
示例3:打印1~100所有偶数
bash
for((i=1;i<=100;i++))
{
x=$[$i % 2]
if [ $x -eq 0 ]
then
echo $i
fi
}
练习2
打印1~200以内的所有奇数求和
bash
tot=0
for((i=1;i<=200;i++))
{
res=$[$i % 2]
if [ $res == 1 ]
then
tot=$(($tot + $i))
fi
}
echo "奇数求和为:"$tot
2. while循环(内容重定向)
语法:
bash
命令A | while read line;
do
循环要做的事情 # $line 指向每一行内容
done
说明:
while read line的功能是逐行遍历命令A的标准输出,每一行的内容都会逐次赋值给变量$line
示例1:删除所有空文件
bash
find /home/hadoop/202608 -type f | while read line;
do
flag=$(du $line | awk -F " " '{print $1}')
if [ $flag -eq 0 ]
then
rm -rf $line
fi
done
示例2:查找文件内容包含"k"的文件
bash
find /home/hadoop -type f | while read line;
do
flag=$(grep "k" $line | wc -l)
if [ $flag -gt 0 ]
then
echo $line
fi
done
示例3:在/tmp目录下找所有文件内容包含"a"的文件
思路:
-
先用
find -type f找到所有/tmp目录下的文件 -
通过
while read line循环遍历 -
通过
grep "a" $line判断是否存在内容"a"
练习3
将 /home/hadoop/2222 目录下所有的文件备份(如:xxx → xxx_bak)
bash
find /home/hadoop/2222 -type f | while read line;
do
cp $line $line"_bak"
done
综合示例
示例1:生成100道随机小学加减法运算题
bash
# $RANDOM : 返回一个随机的整数 [0,3万多]
# $RANDOM % 99 + 1 : 返回随机的 1~99
# read -t 10 -p "请输入你的年龄: " age
read -t 10 -p "请确认,是否需要带出答案:(y/n)" flag
for((i=1;i<=100;i++))
{
num1=$[$RANDOM % 99 + 1]
num2=$[$RANDOM % 99 + 1]
if [ $num1 -le $num2 ]
then
tmp=$num2
num2=$num1
num1=$tmp
fi
x=$[$RANDOM % 2]
if [ $x -eq 0 ]
then
if [ $flag == 'y' ]
then
echo $num1" + "$num2" = "$[$num1 + $num2]
else
echo $num1" + "$num2" = "
fi
else
if [ $flag == 'y' ]
then
echo $num1" - "$num2" = "$[$num1 - $num2]
else
echo $num1" - "$num2" = "
fi
fi
}
示例2:监控磁盘剩余容量
bash
for((i=1;i<=10;i--))
{
desk_free=$(df -h | awk -F " " '{print $4}' | sed -n '6p')
if [ $desk_free -lt 20000 ]
then
echo "磁盘容量不足!" # 发送给指定邮箱
elif [ $desk_free -lt 5000 ]
then
reboot
fi
sleep 2 # 休眠
}
示例3:自动化备份
bash
# 流程:将备份目录压缩成包 → 把包丢到备份目录 → 删除历史备份包
date=$(date +"%Y%m%d")
tar -zcvf $date".tar.gz" /home/hadoop/2608
mkdir -p /home/hadoop/backup
mv $date".tar.gz" /home/hadoop/backup
find /home/hadoop/backup -type f -mtime +7 | xargs rm -rf
示例4:自动化巡检服务日志
bash
find /opt/module/hadoop-3.3.0/logs -name "*.log" | while read line;
do
err_num=$(grep "error" $line | wc -l)
if [ $err_num -eq 0 ]
then
echo $line"是没有报错的!"
else
echo $line"有报错,错误信息,请在 /home/hadoop/1111/err.txt 查阅!"
grep "error" $line >> /home/hadoop/1111/err.txt
fi
done
Shell 脚本的入参
参数变量
| 变量 | 含义 |
|---|---|
$0 |
被调用的脚本文件名 |
$1 |
第一个入参值 |
$2 |
第二个入参值 |
$3 |
第三个入参值 |
$* |
所有的入参集合 |
$# |
入参的个数 |
$? |
判断上一个命令返回的布尔值(真则返回0,否则返回1) |
调用方式
bash
bash
sh shell脚本名 入参1 入参2 入参3 ...
常见面试问答
Q:开发过什么功能性的Shell脚本?
A: 开发过一些自动化备份、打包、巡检等相关的脚本,也封装过一些数据库的脚本执行。