文章目录
- [if 条件语句](#if 条件语句)
- [Shell 函数](#Shell 函数)
-
- [一、 Shell 函数介绍](#一、 Shell 函数介绍)
- [二、 Shell 函数的语法](#二、 Shell 函数的语法)
- [三、Shell 函数的执行](#三、Shell 函数的执行)
-
- [1. 不带参数的函数](#1. 不带参数的函数)
- [2. 带参数的函数](#2. 带参数的函数)
- [四、Shell 函数的基础实践](#四、Shell 函数的基础实践)
- [五、 企业级实践:URL 检测脚本](#五、 企业级实践:URL 检测脚本)
- [六、 函数的递归调用](#六、 函数的递归调用)
if 条件语句
一、if 条件语句基础
1. 作用
类似汉语 "如果... 那么",是 Linux 运维中频繁使用的重要语句,用于根据条件执行不同指令。
2. 语法结构
-
单分支结构:
bash# 格式1 if <条件表达式> then 指令 fi # 格式2(本书主要使用) if <条件表达式>;then 指令 fi当条件表达式成立(真)时,执行 then 后的指令,否则忽略。
-
双分支结构:
bashif <条件表达式>;then 指令集1 else 指令集2 fi条件成立执行指令集 1,否则执行指令集 2。
-
多分支结构
bashif <条件表达式1>;then 指令1 elif <条件表达式2>;then 指令2 else 指令3 fi依次判断条件,满足第一个条件后执行对应指令,都不满足则执行 else 后的指令。
3. 嵌套结构
if 条件语句可嵌套,每个 if 需对应一个 fi,建议缩进保持可读性:
bash
if <条件表达式>;then
if <条件表达式>;then
指令
fi
fi
二、条件表达式类型
if 条件语句中的<条件表达式>可采用以下类型:
-
test 条件表达式:
bashif test 表达式;then 指令 fi -
[] 条件表达式:
bashif [ 字符串 或 算术表达式 ];then 指令 fi -
[[]] 条件表达式:
bashif [[ 字符串 或 算术表达式 ]];then 指令 fi -
(()) 条件表达式:
bashif ((算术表达式));then 指令 fi -
命令表达式:
bashif 命令;then 指令 fi
三、实践示例
-
检测并启动 sshd 服务:
bash# 单分支:未运行则启动 systemctl is-active sshd &>/dev/null if [ $? -ne 0 ];then echo "sshd is not running, I'll start sshd." systemctl start sshd fi # 双分支:运行则输出,否则启动 systemctl is-active sshd &>/dev/null if [ $? -ne 0 ];then echo "sshd is not running." echo -n "Starting sshd ... ..." systemctl start sshd && echo DONE else echo "sshd is running" fi -
通过传参控制 sshd 服务:
bashif [ "$1" == "start" ];then systemctl start sshd elif [ "$1" == "stop" ];then systemctl stop sshd elif [ "$1" == "status" ];then systemctl status sshd elif [ "$1" == "restart" ];then systemctl restart sshd else echo "Usage: $0 start|stop|status|restart " fi -
三个整数从大到小排序:
bash
a=10; b=20; c=30
if [ $a -lt b ] ; t h e n n u m = b ];then num= b];thennum=b;b= a ; a = a;a= a;a=num;fi
if [ $b -lt c ] ; t h e n n u m = c ];then num= c];thennum=c;c= b ; b = b;b= b;b=num;fi
if [ $a -lt b ] ; t h e n n u m = b ];then num= b];thennum=b;b= a ; a = a;a= a;a=num;fi
echo " a > a> a>b>$c"
-
监控系统可用内存:
bashFreeMem=$(free -m | awk 'NR==2 { print $4}') if [ $FreeMem -lt 100 ];then echo "Mem is lower than 100M" | mail -s "FreeMem is ${FreeMem}M" root@localhost fi
配合 crontab 定时任务,每 3 分钟执行一次。
Shell 函数
一、 Shell 函数介绍
- 与 alias 对比 :
- 功能复杂度 :
- alias:仅能替换单条命令(含固定参数),无逻辑能力。
- 函数:支持多命令、条件判断、循环等复杂逻辑。
- 参数处理 :
- alias:不支持动态参数,易出问题。
- 函数:原生支持
$1等参数,灵活可靠。
- 适用场景 :
- alias:简化高频单条命令(如
ll='ls -l')。 - 函数:实现多步骤、带逻辑的任务(如文件备份 + 检查)。
- alias:简化高频单条命令(如
- 功能复杂度 :
- 定义:将多次调用的相同代码组合为函数体并命名,调用时只需使用函数名
二、 Shell 函数的语法
-
标准写法:
bashfunction 函数名 () { 指令... return n } -
简化写法 1(不写 ()):
bashfunction 函数名 { 指令... return n } -
简化写法 2(不写 function):
bash函数名 () { 指令... return n }
三、Shell 函数的执行
1. 不带参数的函数
- 执行方式:直接输入函数名(不带小括号)
- 重要说明:
- 执行时不携带
function关键字和函数后的小括号 - 函数必须在执行前定义或加载
- 程序执行顺序:系统别名 -> 函数 -> 系统命令 -> 可执行文件
- 函数与调用它的脚本共用变量,也可设定局部变量和特殊位置参数
return用于退出函数,exit用于退出脚本文件return返回值给当前程序,exit返回值给当前 Shell- 外部函数文件需用
source或.加载 - 函数内用
local定义局部变量,离开函数后失效
- 执行时不携带
2. 带参数的函数
- 执行方式:
函数名 参数1 参数2 - 参数说明:
- 可使用位置参数(
$1、$2...、$#、$*、$?、$@) - 父脚本参数会被函数参数临时掩盖
$0仍为父脚本名称- 函数执行完成后,原脚本参数恢复
- 函数参数变量在函数体内定义
- 可使用位置参数(
四、Shell 函数的基础实践
- 示例 1 :简单
hello函数(体现函数必须先定义后调用) - 示例 2 :调用外部函数(通过
source加载外部函数文件) - 示例 3 :带参数的
print函数(根据不同参数输出不同颜色文本) - 示例 4 :验证脚本参数与函数参数的关系(脚本参数需显式传递给函数,
$0为脚本名)
五、 企业级实践:URL 检测脚本
- 包含函数:
usage:显示使用方法check_url:通过wget检测 URL 可访问性main:主函数,处理参数并调用检测函数
- 执行逻辑:接收 URL 参数,调用检测函数输出结果
六、 函数的递归调用
-
示例 1:计算 1 到 n 的和(递归累加)
-
示例 2:计算 n 的阶乘(递归累乘)
-
示例 3:fork 炸弹
-
代码:
:(){ :|:& };:解析如下:
-
: () { ... }:定义一个名为 : 的函数
-
: | : &:函数内部递归调用自身两次:
- 第一次调用
:作为管道左半部分 - 第二次调用
:作为管道右半部分
- 第一次调用
-
-
&表示将进程放入后台运行
-
- ; ::定义完成后立即调用这个函数,启动炸弹
工作过程:
- 初始调用
:函数,创建 1 个进程
2. 这个进程会同时创建 2 个新进程(左管道和右管道各一个) - 每个新进程又会创建 2 个进程,以此类推...
4. 进程数量以 2ⁿ 的指数级增长(1→2→4→8→16...),瞬间耗尽系统允许的最大进程数
危害:
-
系统资源被耗尽,正常程序无法启动新进程
-
CPU 占用率飙升至 100%,系统响应极其缓慢
-可能导致系统死机,需要强制重启才能恢复
-解决办法:限制用户进程数量(如 ulimit -u 100)