Linux Shell 编程:条件判断、循环与函数实战指南
在 Linux 运维和开发中,Shell 脚本是自动化任务的利器。无论你是初学者还是有一定经验的开发者,熟练掌握 test、条件判断、循环结构以及函数封装,都能让你的脚本更健壮、更高效。
- 条件判断(如 if、case)让脚本能够根据不同的系统状态或输入做出决策,避免硬编码逻辑,从而提升脚本的适应性和健壮性。
- 循环结构(如 for、while、until)使你能够高效地处理重复性任务,例如批量处理文件或监控进程状态,极大地提升了自动化效率。
- 函数封装将复杂的操作模块化,不仅提高了代码的复用性,还让脚本结构更清晰,便于调试和维护,是构建大型、健壮脚本的基石。本文将系统梳理这些核心知识点,并辅以大量示例,助你快速上手。
1. test 命令与条件测试
Shell 中的条件测试主要通过 test 命令或其等价形式 [ ] 来实现。此外,Bash 还提供了增强版 [[ ]],支持更多特性。
1.1 test 和 [ ] 的基本用法
test 条件表达式
# 或
[ 条件表达式 ] # 注意括号与表达式之间必须有空格
常用测试类型:
- 文件测试:-f(普通文件)、-d(目录)、-e(存在)、-r(可读)、-w(可写)、-x(可执行) 等。
- 字符串测试:-z(空串)、-n(非空)、==(相等)、!=(不等)。
- 数值测试:-eq(等于)、-ne(不等)、-gt(大于)、-lt(小于)、-ge(≥)、-le(≤)。
- 文件比较:
> -nt # test file1 -nt file2 测试file1是否比file2新
> -ot # test file1 -ot file2 测试file1是否比file2旧
> -ef # 测试file1和file2是否为同一个文件。
- 多重条件判断:
-a : test -r file -a -x file
-o : test -r file -o -x file
! : test -r file ! -x file
示例:
[ -f /etc/passwd ] && echo "文件存在"
[ "$USER" = "root" ] && echo "当前是 root"
[ $# -eq 0 ] && echo "没有传入参数"
1.2 [[ ]] 增强测试(Bash 特有)
[[ ]] 是 Bash 的关键字,比 [ ] 更智能:
- 支持 &&、|| 逻辑运算符([ ] 内必须用 -a、-o)。
- 支持正则表达式 =~。
- 支持通配符匹配(如 [[ $str == a* ]])。
- 变量引用时可以不加双引号(但建议加)。
示例:
[[ -z "$var" ]] && echo "var 为空"
[[ $num -gt 10 && $num -lt 20 ]] && echo "num 在 10~20 之间"
[[ $file == *.txt ]] && echo "是 txt 文件"
2.shell脚本
shell脚本可以简单的理解为批处理程序,使用shell脚本可以做如下一些功能:
(1)自动化管理;
(2)管理系统;
(3)简单的入侵侦测功能;
(4)连续指令单一化;
(5)简单的资料处理。
shell脚本注意事项:
指令执行是从上到下、从左到右分析执行的;
指令、选项与参数间的多个空白会被忽略掉;
空白行也会被忽略的;
如果读取到一个enter,就尝试执行该行命令;
#可作为注释,#后面的文字都会被忽略。
shell脚本执行:
绝对路径下达执行:/home/zhang/shell.sh
相对路径下达执行:./shell.sh
将shell.sh放入PATH目录
以bash程式执行:bash shell.sh或sh shell.sh
注意:以上执行方式中,第1-3种方法需要给脚本赋予执行权限才能执行,第4种方式不需要执行权限。
SHELL语法:
#!/bin/bash #宣告这个shell脚本使用的shell名称
程序说明 #程序功能,程序版本,作者等说明
环境变量宣告 #PATH=/bin:/usr/local/bin……….
主程序部分 #主要程序
执行成果告知 #定义返回值 exit 0, exit n
注意:#!/bin/bash 称为Shebang,是 Linux/Unix 系统中脚本文件的第一行特殊标记,由 #! 开头,后接解释器的绝对路径,它的核心作用是告诉操作系统使用哪个解释器来执行该脚本。主程序部分是shell脚本功能的实现。这两个部分是shell脚本必须要有的部分,其他部分可选,但一般为了脚本规范及后期维护,程序说明、环境变量宣告也会添加在脚本中。
如下通过一个简单的脚本说明shell脚本结构:

3. 条件判断:if 语句
if 语句根据命令的退出状态码(0 为真,非 0 为假)来决定执行路径。
3.1 基本结构
if 条件; then
命令
elif 条件; then
命令
else
命令
fi
3.2 实战示例
#!/bin/bash
read -p "请输入一个数字: " num
if [[ $num -eq 0 ]]; then
echo "零"
elif [[ $num -gt 0 ]]; then
echo "正数"
else
echo "负数"
fi
注意:if 后可以直接跟命令,而不只是 test、[]、[[]],例如:
if grep -q "error" /var/log/messages; then
echo "发现错误日志"
fi
4. 多分支选择:case 语句
当分支较多时,case 比嵌套 if-elif 更清晰。
4.1 语法
case 变量 in
模式1)
命令;;
模式2)
命令;;
*)
默认命令;;
esac
4.2 示例:服务管理脚本
#!/bin/bash
case $1 in
start)
echo "启动服务…"
systemctl start myapp
;;
stop)
echo "停止服务…"
systemctl stop myapp
;;
restart)
echo "重启服务…"
systemctl restart myapp
;;
status)
systemctl status myapp
;;
*)
echo "用法: $0 {start|stop|restart|status}"
exit 1
;;
esac
模式支持通配符(*、?、[])和竖线 | 表示或,例如 [yY]|[yY][eE][sS])。
5. 循环结构
5.1 for 循环
for 用于遍历列表或数值范围。
遍历列表:
for name in Alice Bob Charlie; do
echo "Hello, $name"
done
# 遍历文件
for file in *.txt; do
echo "Processing $file"
done
C 风格 for(Bash 支持):
for ((i=1; i<=5; i++)); do
echo "第 $i 次迭代"
done
实用示例:批量重命名:
for f in *.jpg; do
mv "$f" "${f%.jpg}.png"
done
5.2 while 循环
当条件为真时持续执行。
语法:
while 条件; do
命令
done
示例:逐行读取文件:
while IFS= read -r line; do
echo "行内容: $line"
done < /etc/passwd
无限循环:
while true; do
echo "按 Ctrl+C 退出"
sleep 1
done
5.3 until 循环
与 while 相反,当条件为假时执行,直到条件变为真。
语法:
until 条件; do
命令
done
示例:等待某个进程退出:
until ! pgrep -x "myprocess" > /dev/null; do
echo "进程仍在运行,等待中…"
sleep 2
done
echo "进程已退出"
6. 函数封装
函数使脚本模块化,提高复用性和可读性。
6.1 定义与调用
定义格式(两种均可):
function func_name {
# 命令
}
# 或
func_name() {
# 命令
}
调用:直接使用函数名,如 func_name。
6.2 参数与返回值
- 参数通过 $1、$2 … 获取,$# 参数个数,$@ 所有参数。
- return 返回数字状态码(0~255),echo 返回字符串。
示例:加法函数:
add() {
local sum=$(( $1 + $2 ))
echo $sum
}
result=$(add 3 5)
echo "3+5=$result"
带错误处理的函数:
check_file() {
if [[ -f "$1" ]]; then
return 0
else
echo "错误:文件 $1 不存在" >&2
return 1
fi
}
if check_file "/etc/hosts"; then
echo "文件正常"
fi
6.3 变量作用域
默认全局变量,使用 local 声明局部变量(仅在函数内有效)。
my_func() {
local var="局部"
echo $var
}
var="全局"
my_func # 输出 "局部"
echo $var # 输出 "全局"
7. 综合实战:系统健康检查脚本
结合以上所有知识点,编写一个简单的系统检查脚本。
#!/bin/bash
# 系统健康检查
# 函数:检查磁盘使用率
check_disk() {
local threshold=80
local usage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
if [[ $usage -gt $threshold ]]; then
echo "警告:根分区使用率已达 ${usage}%"
else
echo "根分区使用率正常 (${usage}%)"
fi
}
# 函数:检查内存
check_memory() {
local total=$(free -m | awk '/^Mem:/{print $2}')
local used=$(free -m | awk '/^Mem:/{print $3}')
local percent=$(( used * 100 / total ))
echo "内存使用率: ${percent}%"
}
# 函数:检查运行的进程数
check_processes() {
local count=$(ps aux | wc -l)
echo "当前进程数: $count"
}
# 主循环:每隔5秒检查一次(按需修改)
main() {
while true; do
clear
echo "========== 系统健康状态 =========="
check_disk
check_memory
check_processes
echo "=================================="
echo "按 Ctrl+C 退出"
sleep 5
done
}
# 执行主函数
main
8. 最佳实践与注意事项
结语
Shell 脚本中的条件测试、分支判断、循环和函数是构建自动化任务的四大基石。通过本文的梳理和示例,希望你对这些结构有了更清晰的认识。在实际工作中,多写多练,结合系统管理需求不断优化,你的脚本功力定会与日俱增。
如果你有任何疑问或想深入了解某个主题,欢迎在评论区留言交流!
网硕互联帮助中心





评论前必须登录!
注册