Shell 编程(Linux)知识汇总

涵盖 Bash Shell 编程基础、高级特性、最佳实践、常用命令及自动化脚本开发


目录

  1. Shell 基础
  2. 命令执行、管道与重定向
  3. 变量与数据类型
  4. 流程控制
  5. 函数
  6. Bash 高级特性
  7. 文本处理
  8. 文件操作
  9. 进程管理
  10. 网络操作
  11. Shell 脚本最佳实践
  12. 常见陷阱与避坑指南
  13. 常用命令速查
  14. 实战练习

1. Shell 基础

1.1 什么是 Shell

Shell 是用户与 Linux 内核交互的命令行界面,也是一种脚本语言。

1.2 常见 Shell 类型

Shell路径特点
Bash/bin/bash最流行,Linux 默认
Zsh/bin/zsh功能强大,macOS 默认
Fish/usr/bin/fish用户友好,智能补全
Dash/bin/dash轻量,POSIX 兼容
Sh/bin/shPOSIX 标准 Shell

shell 也可分为俩类,一种是系统自带的 Shell,一种是需要额外安装的Shell,在 Linux 上,几乎一定会有 /bin/sh,但 /bin/sh 具体指向谁,不同发行版不一样,

如何查看当前系统有哪些 Shell 呢?

cat /etc/shells 这个文件通常记录“允许作为登录 Shell 的 Shell”

image-20260527213528156

查看当前正在使用的 Shell:

image-20260528150207414

1.3 Shebang(释伴)

只要用了 Bash 特性([[]]、(( ))、数组、${var^^}、进程替换 等),就用 #!/usr/bin/env bash。 纯 POSIX 语法(只用到基础命令、[ ]、for i in),才用 #!/bin/sh。

1.4 脚本执行方式


2. 命令执行、管道与重定向

2.1 退出状态码

每条命令执行后都会返回一个退出状态码,0 通常表示成功,非 0 表示失败。

command 是 bash 的内置命令,不是可执行文件,它的基本作用就是以成功(退出码 0)退出的一个空命令;真正用途,主要是用来绕过函数或别名,直接调用原始命令的。

假设你定义了一个函数覆盖了 ls:

此时调用 ls 会执行这个函数,而不是原来的 ls。如果想跳过函数直接调用系统命令:

command ls

这样就会直接执行 /bin/ls,不会走函数定义。

command -v 用来查看某个命令的路径:

image-20260528152628001

2.2 标准输入、输出和错误

文件描述符名称说明
0stdin标准输入
1stdout标准输出
2stderr标准错误

2.3 管道

2.4 命令替换

推荐使用 $(command),不推荐旧式反引号 `command`,因为前者更清晰且更容易嵌套。

2.5 算术扩展

$((...)) 算术展开

((...)) 算术上下文


3. 变量与数据类型

3.1 变量定义与使用

3.2 变量类型

类型说明示例
局部变量当前 Shell 有效var=value
环境变量子进程可继承export VAR=value
Shell 内置/预定义变量Shell 自动维护的变量$BASH_VERSION, $?, $$

3.3 特殊变量

变量含义
$0脚本名称
$1, $2, ...位置参数
$#参数个数
$@所有参数
$*所有参数
$?上一条命令的退出状态
$$当前进程 PID
$!后台运行的最后一个进程 PID

"$@" 与 "$*" 在加引号时差异很重要,遍历参数时几乎总是使用 "$@"。

3.4 字符串操作

3.5 数组


4. 流程控制

4.1 条件判断

4.2 测试操作符

文件测试

操作符说明
-e file文件存在
-f file是普通文件
-d file是目录
-r file可读
-w file可写
-x file可执行
-s file文件非空

字符串测试

操作符说明
-z str字符串为空
-n str字符串非空
str1 = str2字符串相等
str1 != str2字符串不等

数值比较

操作符说明
-eq等于
-ne不等于
-lt小于
-le小于等于
-gt大于
-ge大于等于

Bash 中更推荐使用 (( ... )) 做整数比较。

正则匹配

=~ 只能在 [[ ... ]] 中使用,捕获组结果保存在 BASH_REMATCH 数组中。

4.3 case 语句

4.4 循环


5. 函数

5.1 函数定义与调用

5.2 函数参数与返回值

5.3 局部变量


6. Bash 高级特性

6.1 进程替换

进程替换可以把命令输出当作文件传给其他命令,常用于避免临时文件。

6.2 mapfile / readarray

mapfile -t 会去掉每行末尾换行符,适合一次性读取小到中等大小文件。

6.3 shopt 常用选项

6.4 trap 信号处理

EXIT 可覆盖正常退出和多数错误退出,但 kill -9 或 exec 替换进程不会触发。


7. 文本处理

7.1 grep - 文本搜索

7.2 sed - 流编辑器

sed 's/old/new/gI' 中的 I 是 GNU sed 扩展,macOS/BSD sed 兼容性可能不同。

7.3 awk - 文本分析工具

7.4 cut - 列提取

7.5 sort - 排序

7.6 uniq - 去重

uniq 只处理连续重复行;如果要全局去重,通常先 sort 再 uniq,或直接使用 sort -u。


8. 文件操作

8.1 文件读写

8.2 文件查找

8.3 文件权限

不要直接对目录树使用 chmod -R 644 /path,目录失去执行权限后会无法进入。


9. 进程管理

9.1 进程查看

9.2 进程控制

9.3 进程优先级


10. 网络操作

10.1 网络测试

端口扫描建议在授权环境中使用;需要更完整的扫描能力时可使用 nmap。

10.2 SSH 操作


11. Shell 脚本最佳实践

11.1 脚本模板

11.2 最佳实践清单

实践说明
使用 set -euo pipefail严格模式,遇错退出
引用变量使用"$var" 而非 $var
使用 [[ 而非 [[[ 更安全,支持更多特性
使用 $(command) 而非 `command`更清晰,可嵌套
使用 readonly 定义常量防止意外修改
使用 local 定义局部变量避免污染全局作用域
检查命令是否存在command -v cmd &> /dev/null
使用 trap 清理资源确保退出时清理
提供使用说明-h 或 --help 选项
日志输出使用颜色和级别区分

11.3 调试技巧


12. 常见陷阱与避坑指南

12.1 变量未加引号

12.2 不要用 for file in $(ls) 遍历文件

12.3 管道中的 while 可能在子 Shell 中执行

推荐:

12.4 set -e 不是万能错误处理

set -e 在 if、while、&&、||、管道等上下文中有例外,关键步骤仍建议显式处理错误。

12.5 文件名以 - 开头时使用 --

12.6 通配符无匹配时的行为

如果没有 .log 文件,默认会保留字面量 *.log。可使用:


13. 常用命令速查

13.1 文件操作

13.2 系统信息

13.3 压缩解压

13.4 用户管理


14. 实战练习

练习目标可用知识点
批量重命名文件给一批文件统一添加前缀或修改扩展名for, 参数展开, mv --
日志统计脚本统计访问日志中的状态码、IP 或错误次数grep, awk, sort, uniq -c
目录备份脚本将指定目录打包并按日期命名tar, date, 变量, 函数
服务健康检查检查端口、HTTP 状态码或进程是否存在curl, ss, pgrep, 退出状态
资源告警脚本检查 CPU、内存或磁盘占用并输出告警df, free, awk, 条件判断

学习资源

在线资源

推荐书籍

  • 《Linux Shell 脚本攻略》
  • 《Shell 脚本学习指南》
  • 《鸟哥的 Linux 私房菜》

实践平台


文档整理于 2026 年 5 月,基于 Bash 4.x/5.x 和 Linux 最佳实践。