1.1 Shell 脚本简介
1.1.1 Shell 的功能与角色
Shell 是 Linux 和 Unix 系统中的命令行解释器,作为用户与操作系统内核之间的交互桥梁。其主要职责包括:- 接收用户输入的指令,解析后提交给系统内核执行;
- 将内核处理的结果通过 Shell 反馈至用户界面;
- 支持脚本编写和批量命令运行,广泛应用于自动化运维、定时任务管理及系统部署等场景。
/bin/bash:目前大多数 Linux 发行版默认使用的 Shell,具备强大功能且兼容性良好;
/bin/sh:轻量级 Shell,某些系统中为 bash 的符号链接;
此外还有 zsh 和 csh 等,它们在语法或功能上有所扩展或差异。
1.1.2 编写首个 Shell 脚本
Shell 脚本本质上是一个包含多条命令的纯文本文件,需遵循特定结构规范: - 文件首行应声明所用解释器,例如:#!/bin/bash此语句指示系统使用 bash 解释器运行该脚本。 - 注释以
# 开头,仅支持单行注释;若需多行注释,可通过块注释方式模拟(如结合 : ' 和 : '注释内容')。
- 脚本文件必须赋予执行权限,否则无法直接运行,设置方法为:chmod +x 脚本名
- 命令按顺序逐行书写,后续章节将介绍逻辑控制结构的应用。
示例:hello.sh 脚本内容#!/bin/bash
# 这是我的第一个Shell脚本(单行注释)
: '
以下是多行注释内容:
功能:输出欢迎信息和系统时间
作者:XXX
日期:2025-11-20
'
echo "Hello, Shell!" # 输出字符串
echo "当前系统时间:$(date)" # 嵌入命令执行结果($() 或 `` 都可)
执行方式如下:
- 直接执行(需事先添加执行权限):
chmod +x hello.sh # 添加执行权限(仅需一次) ./hello.sh # 必须加 ./(当前目录),否则系统会在PATH中查找 - 通过解释器调用执行(无需执行权限):
bash hello.sh # 或 sh hello.sh(若脚本兼容sh) - source 方式执行(命令在当前 Shell 环境中运行,而非子进程):
source hello.sh # 或 . hello.sh(注意点后有空格)
1.1.3 输入输出重定向与管道机制
在默认情况下,每个命令都关联三个标准数据流:- 标准输入(stdin):通常来自键盘,文件描述符为 0;
- 标准输出(stdout):输出至屏幕,文件描述符为
;1 - 标准错误输出(stderr):错误信息也显示在屏幕上,文件描述符为
。2
1. 重定向操作详解
| 操作符 | 作用说明 | 示例 |
|---|---|---|
|
将标准输出重定向并覆盖指定文件(若文件不存在则创建) | (将 ls 结果写入 file.txt,原内容被覆盖) |
|
将标准输出追加到文件末尾 | |
|
将标准错误输出重定向并覆盖文件 | (忽略权限不足产生的错误提示) |
|
将标准错误输出追加至文件 | |
/ |
同时重定向标准输出和标准错误输出(覆盖模式) | |
|
同时追加重定向 stdout 与 stderr | |
|
从文件读取标准输入,代替键盘输入 | (统计文件行数,等效于 wc -l file.txt) |
|
Here Document:嵌入多行文本输入,EOF 可自定义结束标记 | (输入多行内容,以 EOF 为终止符) |
# 向file.txt写入多行内容
cat > file.txt << EOF
第一行内容
第二行内容
第三行:$(date) # 支持嵌入命令
EOF
2. 管道操作(|
)
管道用于将前一个命令的标准输出作为下一个命令的标准输入,从而实现多个命令的串联处理。需要注意的是,管道仅传递 stdout,stderr 不会自动传递,如需转发需显式使用 |2>&1。
基本语法:command1 | command2 | command3 ...
常见应用场景:
- 统计当前目录下文件数量:
ls -l | wc -l # ls -l输出文件列表,wc -l统计行数(含目录总行数) - 筛选包含 “error” 关键字的日志行:
cat app.log | grep "error" # grep 过滤关键字 - 对输出结果排序并去除重复项:
cat numbers.txt | sort | uniq -c # sort排序,uniq -c 统计重复次数 - 将错误信息也送入管道进行处理:
find / -name "test" 2>&1 | grep "Permission" # 过滤权限错误信息
1.2 Shell 变量的概念与分类
变量是 Shell 中用于存储数据的基本单元,可用于保存字符串、数值等信息,在脚本中实现动态赋值与重复引用。1.2.1 用户自定义变量
这类变量由用户自行创建、修改和使用,默认作用范围限于当前脚本或 Shell 会话。1. 定义新变量
语法格式为:变量名=值注意:等号两侧不能留空格。 命名规则:
- 只能由字母、数字和下划线组成,且不能以数字开头;
- 区分大小写,例如
与NAME
视为两个不同变量;name - 建议采用全大写字母命名,以符合通用规范,并避免与系统预设变量冲突。
NAME="Zhang San" # 字符串值可加引号(推荐,避免空格等特殊字符问题)
AGE=25 # 数值型变量无需加引号
SCORE=95.5 # 支持浮点数(但Shell默认不支持浮点运算,需借助bc)
FILE_PATH="/home/user/file.txt" # 路径变量
2. 查看与引用变量值
查看变量内容可使用:echo $变量名 或 echo ${变量名}其中
{} 可明确界定变量边界,防止解析歧义。
引用变量时使用:$变量名 或 ${变量名}可在双引号字符串中直接嵌入变量值。 示例:
NAME="Li Hua"
echo $NAME # 输出:Li Hua
echo "姓名:${NAME}" # 输出:姓名:Li Hua(推荐用{},边界清晰)
# 避免歧义示例
echo "Hello${NAME}World" # 正确:HelloLi HuaWorld
echo "Hello$NAMEWorld" # 错误:Shell会认为变量是NAMEWorld(未定义,输出Hello)
3. 特殊赋值方式
| 赋值方式 | 功能说明 | 示例 |
|---|---|---|
| 空值赋值 | 将变量设为空字符串 | 或 |
| 取消变量 | 使用 unset 命令删除已定义的变量 | (执行后 $NAME 不再有输出) |
| 从命令输出赋值 | 利用 $() 或 `` 捕获命令执行结果(推荐使用 $(),更具可读性和嵌套兼容性) | (获取当前日期时间) |
| 从文件内容赋值 | 通过 $(cat 文件名) 读取整个文件内容 | |
| 条件赋值(${} 扩展语法) | 当变量未定义或为空时,提供默认值(不影响原变量) | (仅在访问时使用默认值,VAR 本身不变) |
变量不存在或为空时的默认值设置与修改
当变量未定义或其值为空时,可通过特定语法为其赋予默认值,并实现对变量 VAR 的更新操作。
${VAR:=默认值}
(永久性修改 VAR)
示例:条件赋值操作
# 场景:若未定义USER,默认使用"guest"
echo ${USER:-guest} # 若USER已定义(如root),输出root;否则输出guest
# 场景:若未定义AGE,设置AGE=18并使用
echo ${AGE:=18} # 若AGE未定义,输出18且AGE变量被设为18;已定义则输出原值
变量作用域的配置方法
在默认情况下,用户自定义的变量仅在当前 Shell 环境或脚本中有效。这意味着子 Shell(例如由脚本启动的子进程、管道符后的命令等)无法访问这些变量。
通过使用以下方式,可将普通变量升级为环境变量,使其能够在子进程中被继承和使用:
export
- 临时生效(限于当前会话):
export 变量名- 或
export 变量名=值
- 全局范围(所有用户): 修改系统级配置文件
或/etc/profile
,并在其中添加/etc/environment
;export 变量名=值 - 当前用户专用: 编辑用户级配置文件
或~/.bashrc
,并加入~/.bash_profile
;export 变量名=值
- 执行
或source /etc/profile
,无需重启当前 Shell 即可加载新设置。source ~/.bashrc
示例:环境变量的实际设置过程
# 临时设置环境变量(当前Shell及子Shell生效)
export JAVA_HOME="/usr/local/jdk"
export PATH="$PATH:$JAVA_HOME/bin" # 追加PATH路径
# 永久设置(当前用户)
echo 'export JAVA_HOME="/usr/local/jdk"' >> ~/.bashrc
echo 'export PATH="$PATH:$JAVA_HOME/bin"' >> ~/.bashrc
source ~/.bashrc # 立即生效
数值计算处理(借助 bc 工具)
Shell 原生仅支持整数运算,通常通过
$((...)) 或 expr 实现。对于浮点数运算或更复杂的数学操作(如四则混合运算、三角函数等),需要依赖外部工具 bc(该工具为 Linux 系统自带,若缺失需通过 yum install bc 安装)。
(1)整数运算的两种方式
方式一:
$(( 表达式 ))
推荐使用此法,语法简洁清晰。
a=10
b=5
echo $((a + b)) # 15
echo $((a - b)) # 5
echo $((a * b)) # 50(注意:* 无需转义)
echo $((a / b)) # 2(整数除法,舍去小数)
echo $((a % b)) # 0(取余)
echo $((a++)) # 10(先使用后自增)
echo $((++a)) # 12(先自增后使用)
方式二:
expr 表达式
注意:运算符前后必须有空格,且乘号 * 需进行转义处理。
expr 10 + 5 # 15
expr 10 \* 5 # 50(* 必须转义)
(2)浮点数及复杂运算(使用 bc 工具)
基本语法格式为:
echo "表达式" | bc
常用参数说明:
:启用数学库,支持浮点运算、三角函数、对数等高级功能;-l
:设定小数点后保留位数(默认为 0,即只输出整数部分)。scale=N
示例:
# 浮点数加法(保留2位小数)
echo "scale=2; 3.14 + 2.86" | bc # 6.00
# 浮点数乘法
echo "1.2 * 3.4" | bc # 4.08(未加-l,仍支持基础浮点)
# 三角函数(需加-l加载数学库,弧度制)
echo "scale=4; sin(3.1416/2)" | bc -l # 1.0000(sin(π/2)=1)
# 变量参与计算
x=5.5
y=2.2
echo "scale=1; $x / $y" | bc # 2.5
1.2.2 特殊 Shell 变量类型
这类变量由 Shell 内部预先定义,无需手动创建,主要用于获取系统状态、脚本输入参数、命令执行结果等关键信息。
1. 环境变量
系统预设的一类变量,用于控制 Shell 行为和程序运行环境,命名通常采用全大写形式。可通过
env 或 printenv 查看全部环境变量列表。
| 变量名 | 作用说明 | 示例 |
|---|---|---|
|
指定命令搜索路径(即可执行程序所在的目录列表) | (输出示例:/usr/bin:/bin:...) |
|
表示当前用户的主目录路径 | (输出示例:/home/user) |
|
记录当前登录系统的用户名 | (输出:root 或 user) |
|
当前用户的 UID(用户标识号,root 用户为 0) | (输出:0 或 1000) |
|
当前工作目录的完整路径 | (输出:/home/user/work) |
|
正在使用的 Shell 解释器路径 | (输出:/bin/bash) |
|
系统语言与字符编码设置 | (输出:zh_CN.UTF-8) |
|
上一条命令的退出状态码(0 表示成功,非 0 表示失败) | (输出 0 表示执行成功) |
示例:环境变量的应用场景
echo "当前用户:$USER,主目录:$HOME"
echo "命令搜索路径:$PATH"
echo "上一条命令执行结果:$?" # 0表示成功,非0表示失败(如127=命令未找到)
2. 位置变量
用于接收脚本运行时传入的命令行参数,格式为
$n(n 为正整数,取值范围 1–9;当 n ≥ 10 时需写作 ${10})。
| 变量名 | 作用说明 |
|---|---|
|
脚本文件自身的名称(包含执行路径,若指定了路径运行) |
|
分别代表第 1 至第 9 个命令行参数 |
|
用于获取第 10 个及以后的参数(必须配合 {} 使用) |
|
统计传入的所有命令行参数的数量 |
|
将所有参数作为一个整体字符串输出 |
|
将所有参数以独立字符串数组的形式传递 |
示例:编写一个使用位置变量的脚本(param.sh)
#!/bin/bash
echo "脚本名:$0"
echo "第1个参数:$1"
echo "第2个参数:$2"
echo "第10个参数:${10}" # 注意{}
echo "参数总个数:$#"
echo "所有参数($*):$*"
echo "所有参数($@):$@"
# 遍历所有参数($@更适合循环)
echo "遍历参数($@):"
for arg in "$@"; do
echo "- $arg"
done
执行脚本并传参:
chmod +x param.sh
./param.sh a b c d e f g h i j k # 传入11个参数
预期输出结果:
脚本名:./param.sh
第1个参数:a
第2个参数:b
第10个参数:j
参数总个数:11
所有参数($*):a b c d e f g h i j k
所有参数($@):a b c d e f g h i j k
遍历参数($@):
- a
- b
- ...(省略中间参数)
- k
3. 预定义变量
这些是 Shell 内建的特殊变量,用于提取命令执行状态、进程 ID 等核心运行时信息,用户不可手动修改。
| 变量名 | 作用说明 | 示例 |
|---|---|---|
|
上一条命令的退出状态码(0 表示成功,非 0 表示失败) | (输出 2,表示失败) |
|
当前 Shell 进程的 PID(进程标识号) | (输出示例:12345) |
|
最近一个后台任务的进程 ID | (显示后台运行的进程编号) |
|
再次强调:上一条命令的退出状态——最常使用的判断依据 | (0 表示脚本成功执行) |
|
当前 Shell 启动时所使用的选项标志(如 h=hashall, i=interactive) | (输出:himBH) |
|
上一条命令使用的最后一个参数内容 | (输出:/tmp) |
示例:预定义变量的实际应用演示
# 1. $?:判断命令是否执行成功
ping -c 1 www.baidu.com &> /dev/null
if [ $? -eq 0 ]; then
echo "百度可通"
else
echo "百度不可通"
fi
# 2. $$:获取当前脚本PID(可用于生成唯一文件名)
echo "当前脚本PID:$$"
temp_file="temp_$$.txt" # 生成唯一临时文件名
echo "临时文件:$temp_file"
# 3. $!:获取后台进程PID
sleep 30 & # 后台运行sleep命令
echo "后台进程PID:$!"
kill $! # 终止后台进程
总结
Shell 脚本编写中的核心规范之一是使用 shebang 声明:
#!/bin/bash变量主要分为两类:自定义变量和特殊变量。自定义变量由用户自行定义,而特殊变量则包括环境变量、位置变量以及预定义变量,它们在脚本运行过程中起到关键作用。
在数值运算方面,整数计算通常使用特定命令实现,相关示例如下:
$((...))
对于浮点数或更复杂的数学运算,则需借助专门的工具进行处理,示例如下:
bc
位置变量是脚本参数传递的重要手段,能够灵活接收外部输入,其用法参考:
$1~$n
此外,另一个脚本自动化中不可或缺的元素是预定义变量中的执行状态码,用于获取上一条命令的执行结果,标记如下:
$?
关于权限控制、代码注释与命令执行顺序的规范也至关重要,应确保脚本具备清晰的注释、正确的执行权限设置;
重定向机制可用于调整输入输出的数据流向,而管道则常用于多个命令之间的协作处理。


雷达卡


京公网安备 11010802022788号







