跟着 AI 学 (一)- shell 脚本

bash 复制代码
echo "开始编译..."
CURRENT_PATH=`pwd`
CACHE_BASE_PATH=/data/cache/$PROJECT_NAME/$DEPOT_NAME/$CCI_JOB_NAME

# 根据参数决定是否清除缓存
if [ "$CLEAR_CACHE" = "true" ]; then
echo "清除 node_modules 缓存..."
rm -rf $CACHE_BASE_PATH/node_modules
fi

mkdir -p $CACHE_BASE_PATH/node_modules
docker run --network=host --rm \
-v $CURRENT_PATH:/root/workspace \
-v $CACHE_BASE_PATH/node_modules:/root/workspace/node_modules \
-v /data/cache/yarn/v6:/usr/local/share/.cache/yarn/v6 \
-e CI_ENV=1 \
coding-public-docker.pkg.coding.net/public/docker/nodejs:20-2024.01 \
/bin/bash -c "yarn install --frozen-lockfile && yarn build:sit && tar zcvf app-dom_front_sit.tar.gz dist"
echo "编译打包过程结束"

Shell 脚本逐行解析

脚本概述

这是一个用于 CODING CI/CD 构建流程的 Shell 脚本,主要功能是使用 Docker 容器编译前端项目并打包。


逐行代码解析

第 1 行:输出提示信息

bash 复制代码
echo "开始编译..."

说明 : 使用 echo 命令输出提示信息到终端,告诉用户脚本开始执行了。


第 2 行:获取当前工作目录

bash 复制代码
CURRENT_PATH=`pwd`

说明:

  • pwd 命令获取当前工作目录的完整路径
  • 反引号 pwd 表示命令替换,会执行 pwd 命令并将结果赋值给变量
  • CURRENT_PATH 变量保存了当前目录路径
  • 例如:/root/workspace/your-project

第 3 行:构建缓存路径

bash 复制代码
CACHE_BASE_PATH=/data/cache/$PROJECT_NAME/$DEPOT_NAME/$CCI_JOB_NAME

说明:

  • 定义缓存基础路径变量
  • $PROJECT_NAME$DEPOT_NAME$CCI_JOB_NAME 是引用的环境变量(在脚本外部定义)
  • 这行构建了一个分层的缓存目录结构
  • 例如:/data/cache/myproject/frontend/build-job-01

第 5-9 行:条件清除缓存

bash 复制代码
if [ "$CLEAR_CACHE" = "true" ]; then
    echo "清除 node_modules 缓存..."
    rm -rf $CACHE_BASE_PATH/node_modules
fi

说明:

第 6 行 - 条件判断:

  • if 条件判断语句开始
  • [ ] 是测试命令(test 命令的另一种写法)
  • "$CLEAR_CACHE" 引用环境变量(加引号防止变量为空时出错)
  • = 是字符串相等比较运算符
  • then 表示如果条件为真,执行下面的命令

第 7 行 - 输出提示:

  • 输出清除缓存的提示信息

第 8 行 - 删除缓存:

  • rm -rf 递归强制删除目录及其内容
    • -r: 递归删除目录
    • -f: 强制删除,不提示确认

第 9 行 - 结束条件块:

  • fi 结束 if 语句块(if 的反向拼写)

第 11 行:创建缓存目录

bash 复制代码
mkdir -p $CACHE_BASE_PATH/node_modules

说明:

  • 创建缓存目录
  • -p 参数:如果父目录不存在则自动创建,且如果目录已存在不报错
  • 确保缓存目录存在,即使之前被删除了

第 12-18 行:启动 Docker 容器并执行编译

bash 复制代码
docker run --network=host --rm \
-v $CURRENT_PATH:/root/workspace \
-v $CACHE_BASE_PATH/node_modules:/root/workspace/node_modules \
-v /data/cache/yarn/v6:/usr/local/share/.cache/yarn/v6 \
-e CI_ENV=1 \
coding-public-docker.pkg.coding.net/public/docker/nodejs:20-2024.01 \
/bin/bash -c "yarn install --frozen-lockfile && yarn build:sit && tar zcvf app-dom_front_sit.tar.gz dist"

说明:

第 12 行 - Docker 运行命令:

  • docker run: 启动 Docker 容器
  • --network=host: 容器使用宿主机的网络栈(容器可以直接访问宿主机网络)
  • --rm: 容器退出后自动删除
  • \ 是行连接符,表示命令在下一行继续

第 13-15 行 - 挂载卷:

  • -v 挂载卷(volume),将宿主机目录映射到容器内
  • 格式:宿主机路径:容器内路径
  • 第 13 行:挂载当前项目目录到容器的 /root/workspace
  • 第 14 行:挂载 node_modules 缓存目录(实现依赖缓存复用)
  • 第 15 行:挂载 yarn 全局缓存目录(加速 yarn 包下载)

第 16 行 - 设置环境变量:

  • -e 设置容器内的环境变量
  • CI_ENV=1 告诉程序当前在 CI(持续集成)环境中运行

第 17 行 - 指定镜像:

  • 指定要使用的 Docker 镜像
  • 这是一个 CODING 提供的 Node.js 20 镜像(2024.01 版本)

第 18 行 - 容器内执行命令:

  • /bin/bash -c "命令": 在容器内执行 bash 命令
  • && 逻辑与操作符,前一个命令成功才执行下一个
  • yarn install --frozen-lockfile: 安装依赖,不更新 lockfile(保证依赖版本一致)
  • yarn build:sit: 执行 sit 环境的构建命令
  • tar zcvf app-dom_front_sit.tar.gz dist: 将 dist 目录打包成压缩文件
    • z: 使用 gzip 压缩
    • c: 创建归档文件
    • v: 显示详细过程
    • f: 指定文件名

第 19 行:输出完成信息

bash 复制代码
echo "编译打包过程结束"

说明: 输出完成提示信息,表示整个编译打包流程已结束。


执行环境说明

脚本执行层次

bash 复制代码
CODING 构建机器(宿主机)
├── Shell 脚本在这里执行
├── 代码目录(从 Git clone 过来)
└── 启动 Docker 容器
    └── 容器内执行编译命令

执行流程

  1. CODING 分配构建机器

    • 构建机器上已安装 Docker
    • 代码自动从 Git 仓库 clone 到工作目录
  2. Shell 脚本在宿主机上运行

    • 获取路径、准备缓存目录
    • 根据条件清除旧缓存
  3. 启动 Docker 容器

    • 容器提供隔离的、统一的编译环境
    • 通过卷挂载访问宿主机上的代码和缓存
  4. 容器内执行编译

    • 安装依赖、构建项目、打包产物
    • 产物保存在挂载的宿主机目录中

为什么这样设计?

层级 作用 优势
宿主机 运行脚本、管理资源、缓存 持久化缓存、灵活控制
Docker 容器 提供编译环境 环境一致性、版本锁定、隔离性

学习 Shell 脚本编写

1. 基础知识学习路径

  • 变量和引用 : 变量定义、引用($VAR)、命令替换(cmd$(cmd)
  • 条件判断 : if-then-else、测试表达式 [ ][[ ]]
  • 循环结构 : forwhileuntil
  • 函数定义: 如何封装可重用代码
  • 输入输出 : echoread、重定向(>>><)、管道(|

2. 常用命令掌握

文件操作:

  • ls - 列出目录内容
  • cd - 切换目录
  • mkdir - 创建目录
  • rm - 删除文件/目录
  • cp - 复制文件
  • mv - 移动/重命名文件

文本处理:

  • grep - 搜索文本
  • sed - 流编辑器
  • awk - 文本分析工具
  • cut - 剪切文本列
  • sort - 排序

系统信息:

  • pwd - 显示当前目录
  • whoami - 显示当前用户
  • ps - 进程状态
  • df - 磁盘使用情况
  • du - 目录空间使用

3. 实践建议

  1. 从简单脚本开始: 写一些自动化日常任务的小脚本
  2. 阅读现有脚本: 分析项目中的脚本(就像这个)
  3. 使用 shellcheck: 静态分析工具,帮助发现错误和不规范写法
  4. 学习最佳实践 :
    • 变量加引号("$VAR")防止空格问题
    • 使用 set -e 遇错即停
    • 添加注释说明脚本功能
    • 检查命令执行结果

4. 推荐学习资源

  • 在线教程 : Shell 脚本编程30分钟入门
  • 书籍: 《Linux命令行与shell脚本编程大全》
  • 实践平台: 在自己的项目中逐步应用
  • 工具: 使用 VSCode + ShellCheck 插件

5. 针对这个脚本的学习点

  • Docker 命令的使用: 理解容器化构建的优势
  • CI/CD 环境变量的应用: 如何在构建流程中传递配置
  • 缓存策略的实现: 优化构建速度的关键技术
  • 构建流程的自动化: 从代码到产物的完整流程

常见问题

Q: 为什么要用 Docker 容器编译?

A: 保证编译环境的一致性,避免"在我机器上可以运行"的问题。容器提供了固定版本的 Node.js、系统库等依赖。

Q: 缓存机制如何工作?

A: 通过挂载宿主机的缓存目录到容器,node_modules 和 yarn 缓存可以在多次构建之间复用,大幅提升构建速度。

Q: --frozen-lockfile 有什么作用?

A: 确保安装的依赖版本与 yarn.lock 文件完全一致,不会自动更新依赖版本,保证构建的可重复性。

Q: 如何调试这个脚本?

A: 可以在脚本中添加 set -x 开启调试模式,或添加更多 echo 语句输出关键变量值。

相关推荐
clownAdam3 小时前
Chrome性能优化秘籍
前端·chrome·性能优化
@Kerry~3 小时前
phpstudy .htaccess 文件内容
java·开发语言·前端
@PHARAOH5 小时前
WHAT - 前端性能指标(交互和响应性能指标)
前端·交互
噢,我明白了5 小时前
前端js 常见算法面试题目详解
前端·javascript·算法
im_AMBER5 小时前
Web 开发 30
前端·笔记·后端·学习·web
Jonathan Star5 小时前
Webpack 打包优化与骨架屏结合:双管齐下提升前端性能与用户体验
前端·webpack·ux
做好一个小前端5 小时前
后端接口获取到csv格式内容并导出,拒绝乱码
前端·javascript·html
第七种黄昏5 小时前
前端面试-箭头函数
前端·面试·职场和发展
Youyzq6 小时前
前端box-shadow出现兼容性问题如何处理
前端