本章目标:掌握大型 Shell 项目的结构化组织方式,提升脚本工程化能力。
一、为什么要模块化与结构化?
随着脚本体积增大:
- 单文件维护困难
- 不同功能重复开发
- 缺乏复用和配置能力
- 难以调试与协作
模块化、结构化可以解决这些问题,让脚本像程序一样开发与维护。
二、典型 Shell 项目结构
my-shell-project/
├── bin/ # 可执行脚本
│ └── backup.sh
├── lib/ # 公共函数库
│ ├── config.sh
│ └── utils.sh
├── logs/ # 日志文档存储
├── conf/ # 配置文档
│ └── backup.conf
├── tmp/ # 临时数据
├── README.md # 项目说明
└── run.sh # 主入口脚本
三、模块化基础:函数库与配置
1. 编写通用函数模块(lib/utils.sh)
log() {
echo "[$(date '+%F %T')] $1"
}
2. 编写配置模块(lib/config.sh)
BACKUP_SRC="/home/user/data"
BACKUP_DST="/backup"
3. 在主脚本中加载模块
#!/bin/bash
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$BASE_DIR/lib/config.sh"
source "$BASE_DIR/lib/utils.sh"
log "开始备份..."
# 业务逻辑
四、配置文件与参数解耦
可以将参数抽出为 .conf 配置文件,便于修改与多环境部署。
示例配置文件(conf/backup.conf):
SRC_DIR="/home/user/data"
DST_DIR="/mnt/backup"
读取配置文件:
source ./conf/backup.conf
五、支持命令参数与子命令(进阶)
case "$1" in
backup)
./bin/backup.sh
;;
clean)
./bin/clean.sh
;;
*)
echo "Usage: $0 {backup|clean}"
exit 1
;;
esac
六、添加日志机制与错误处理
LOG_FILE="./logs/backup_$(date +%F).log"
exec > >(tee -a "$LOG_FILE") 2>&1
trap 'echo "[ERROR] 执行失败:$BASH_COMMAND"' ERR
七、增加 Makefile(可选)
为统一执行入口,可创建 Makefile:
run:
bash run.sh backup
clean:
rm -rf tmp/*
运行命令:
make run
八、版本控制与多人协作
使用 Git 管理 Shell 项目:
git init
echo "logs/" >> .gitignore
多人协作:
- 每人维护一个模块或功能
- 使用 Pull Request 审核合并
- 用注释和 README 文档保持可读性
九、良好结构的 Shell 项目案例参考
项目目录结构越清晰,越容易维护和拓展。
推荐阅读:
- bash boilerplate
- bashly (命令行构建器)
十、小结:写出专业 Shell 工程的建议
建议 | 说明 |
拆分逻辑为函数模块 | 每个功能单独成库文件 |
配置参数外部化 | .conf 文件集中管理 |
加入日志与错误处理 | 提高可追踪性 |
提供统一入口与使用说明 | run.sh + README.md |
使用 Git 管理和协作 | 项目规范 + 版本控制 |
保持简洁易读 | 避免嵌套过深、命名清晰 |
下一篇预告:
Linux Shell 入门教程(十五):Shell 脚本安全性与最佳实践
将讲解如何防止脚本误删文件、权限泄露、防止注入等问题,保障脚本安全运行。