${var:-default}用于关键字段兜底,不依赖变量是否定义或为空,避免模板因空值渲染出错或引发安全风险;它只读取不赋值,适合模板原位展开,配合export和envsubst使用,并对强依赖字段改用${var:?err}校验。

直接用 ${var:-default} 语法,不用提前判断或赋值,就能安全兜底。
为什么需要默认值
Shell 不报未定义变量错误,而是静默展开为空字符串。这看似友好,实则埋雷:空值参与路径拼接、端口绑定、数据库连接时,可能引发服务启动失败、配置错乱甚至安全暴露。比如 PORT= 导致监听随机端口,DATABASE_URL= 可能连上本地 socket。
两种常用语法的区别和选择
${var:-default} 和 ${var:=default} 都能在变量未定义或为空时返回默认值,关键区别在于是否修改原变量:
-
${var:-default}:只读取,不赋值。适合模板渲染、日志输出等“用完即弃”场景 -
${var:=default}:既返回默认值,也把默认值写入var。适合初始化配置变量,后续还要多次引用
位置参数(如 、)只能用 :- 形式设默认值,:= 不支持。
在配置模板中直接使用
不要先写 PORT=${PORT:-8080} 再用 $PORT,而是在模板里原位展开:
listen ${PORT:-8080};error_log /var/log/app/${APP_NAME:-myapp}.log ${LOG_LEVEL:-warn};timeout ${TIMEOUT:-30}s;
这样即使 PORT 完全没声明,也不会出错,结果确定可预期。
配合 export 和 envsubst 正确生效
如果用 envsubst 渲染模板,必须确保变量已导出:
- 未
export的变量,envsubst看不到,模板里仍留着$PORT原样字符串 - 推荐写法:
export PORT=${PORT:-3000} API_URL=${API_URL:-https://api.example.com},再执行envsubst config.yaml
对强依赖字段(如 DB_HOST),建议改用 ${DB_HOST:?DB_HOST is required} 主动报错,而不是静默兜底。











