${var:-default}用于关键字段兜底,不依赖变量是否定义或为空,如port、database_url、log_level等必需项;模板中直接展开,配合set -u和${var:?err}校验强依赖字段,未导出变量需先export再供envsubst使用。

用 ${var:-default} 填充关键字段,核心是“不依赖变量是否已定义或是否为空”,只要字段没值就兜底,避免模板因空值渲染出错或产生安全隐患。
识别哪些字段必须设默认值
配置模板里容易缺失的关键字段通常包括:服务监听端口、数据库主机、日志级别、超时时间、API 地址等。这些不是可选参数,而是运行必需项。例如:
-
PORT缺失 → 服务可能绑定到 0 或随机端口,暴露风险 -
DATABASE_URL为空 → 脚本可能连接本地 socket 或报错退出 -
LOG_LEVEL未设 → 默认可能是debug,泄露敏感信息
在模板中直接使用 ${var:-default} 渲染
不要先赋值再引用,而是在模板输出位置直接展开。比如生成 Nginx 配置片段:
listen ${PORT:-8080};
proxy_connect_timeout ${TIMEOUT:-60};
error_log /var/log/nginx/${APP_NAME:-app}.error.log ${LOG_LEVEL:-warn};
这样即使 PORT 完全未 export,也不会报错,且结果确定可预期。
配合 set -u 提前暴露未声明变量(推荐)
在脚本开头加 set -u,让未声明的变量访问直接报错——这看似矛盾,实则是主动防御:
- 它能捕获拼写错误(如把
DB_HOST写成DB_HOTS),而${DB_HOTS:-localhost}会静默兜底,掩盖问题 - 兜底只用于“业务上允许缺失”的字段,比如
ADMIN_EMAIL;但DB_HOST这类强依赖字段应强制要求提供,或通过环境检查流程拦截 - 真正安全的做法是:对关键字段用
${var:?err_msg}校验,非关键字段才用${var:-default}
注意变量作用域与导出时机
Shell 中未 export 的变量,在子 shell(如 $(...) 或管道中)不可见。若模板由 envsubst 或 sed 处理,需确保变量已导出:
export PORT=${PORT:-3000}
export API_URL=${API_URL:-"https://api.example.com"}
envsubst config.yaml
否则 envsubst 看不到未导出的变量,仍会留下 $PORT 原样字符串。











