写出第一个 shell 脚本
目标
完整练习一遍 shell 脚本的基本骨架:shebang、执行权限、参数、环境变量、条件分支和退出码。
为什么重要
脚本往往不是由人调用,而是由其他程序调用。因此,输出流与退出码就是接口。结果写入 stdout,错误和用法写入 stderr,成功或失败通过退出码表示——只有遵守这一约定,result=$(script.sh) 这样的用法才能成立,CI 也才能检测到失败。一旦把用法说明输出到 stdout,它就会变成结果值的一部分。配置则应通过环境变量传入,未设置时使用合理默认值运行,这是部署自动化的标准方式。
步骤
- 创建
/root/bin/greet.sh,第一行写成#!/bin/bash。 - 为该文件添加执行权限。
- 运行
greet.sh labhub时,必须准确输出Hello, labhub!。 - 设置默认值,使不带参数运行时输出
Hello, world!。传入参数时仍必须使用该参数。 - 如果环境变量
GREETING已设置,就用其值替换问候语。GREETING=Hi greet.sh labhub应输出Hi, labhub!;未设置时使用Hello;GREETING=Yo greet.sh应输出Yo, world!。 - 创建
/root/bin/checkfile.sh <경로>。普通文件输出file,目录输出dir,不存在则输出missing。 - 创建
/root/bin/grade.sh <점수>。90 以上输出A,80~89 输出B,70~79 输出C,低于 70 输出F。 - 创建
/root/bin/deploy.sh。读取环境变量APP_ENV:- 未设置时,向标准错误输出提示,并以退出码
2结束 - 值不是
prod/stage时,以退出码3结束 - 值为
prod或stage时,输出deploying to <값>并以退出码0结束
- 未设置时,向标准错误输出提示,并以退出码
提示
${1:-world}只在第一个参数不存在或为空时使用 world。- 使用
echo "메시지" >&2写入标准错误。 - 常见错误 1:第 5 步为了给环境变量设置默认值而覆盖位置参数,会破坏第 4 步。二者必须独立工作。
- 常见错误 2:第 7 步必须使用
>=;如果改用>,90 会被判为 B。请逐一手动测试边界值。
脚本文件与 shebang
创建 /root/bin/greet.sh,第一行写成 #!/bin/bash。
第一行的 #! 用于告诉内核应使用哪个解释器来运行该文件。
添加执行权限
为该文件添加执行权限。
使用 chmod +x 开启执行位。
接收参数并输出
运行 greet.sh labhub 时,必须准确输出 Hello, labhub!。
第一个位置参数是 $1。逗号和感叹号的位置也必须完全准确。
处理参数默认值
设置默认值,使不带参数运行时输出 Hello, world!。传入参数时仍必须使用该参数。
使用 ${1:-默认值} 语法,只在没有参数时才使用默认值。存在参数时必须原样保留。
通过环境变量更改问候语
如果环境变量 GREETING 已设置,就用其值替换问候语。GREETING=Hi greet.sh labhub 应输出 Hi, labhub!;未设置时使用 Hello;GREETING=Yo greet.sh 应输出 Yo, world!。
环境变量和位置参数都需要处理默认值,并且不能彼此干扰。
判断文件类型
创建 /root/bin/checkfile.sh <경로>。普通文件输出 file,目录输出 dir,不存在则输出 missing。
-f 和 -d 分别检查普通文件与目录。顺序设置错误可能会让目录落入 missing 分支。
评定分数等级
创建 /root/bin/grade.sh <점수>。90 以上输出 A,80~89 输出 B,70~79 输出 C,低于 70 输出 F。
边界值最容易出错。请分别手动测试 90 与 89、80 与 79、70 与 69。
验证环境变量与退出码
创建 /root/bin/deploy.sh。读取环境变量 APP_ENV:
- 未设置时,向标准错误输出提示,并以退出码
2结束 - 值不是
prod/stage时,以退出码3结束 - 值为
prod或stage时,输出deploying to <값>并以退出码0结束
必须区分标准输出和标准错误,并针对不同情况返回不同退出码。exit 后面的数字就是约定。