Shell Daily 2026-01-30: 变量替身 (Envsubst)
Shell Daily 2026-01-30: 变量替身 (Envsubst)
在容器化(Docker/Kubernetes)大行其道的今天,我们经常需要把环境变量(如数据库地址、API 密钥)注入到配置文件中。
很多人至今还在用 sed 编写复杂的正则表达式来替换占位符:sed -i "s/{{DB_HOST}}/$DB_HOST/g" config.yml。这种做法不仅难写,而且遇到包含特殊字符(如 / 或 &)的变量时,sed 会直接报错。
其实,GNU Gettext 包中藏着一个专门干这事的神器:envsubst。
怎么用
它读取标准输入,将其中的 Shell 风格变量($VAR 或 ${VAR})直接替换为当前环境变量的值,然后输出。
- 语法:
envsubst < template_file > output_file - 兼容性:Linux (GNU gettext) 标配。Alpine 镜像通常需安装
gettext包。
适用场景
- Docker 启动脚本:在容器启动瞬间,利用环境变量生成最终的
nginx.conf或application.yml。 - CI/CD 模板渲染:在部署流水线中生成 Kubernetes Manifest 文件。
示例 1:极简替换 (The Clean Way)
告别丑陋的 sed 占位符 {{...}},直接在模板里写标准的 $VAR。
# 1. 准备模板 (redis.conf.template)
# 这里的 $REDIS_PORT 是我们想替换的,但 $pid 是配置文件自带的,不能动!
$ cat redis.conf.template
port $REDIS_PORT
pidfile /var/run/redis_$pid.pid
# 2. 注入环境变量
$ export REDIS_PORT=6379
# 注意:如果不加参数,envsubst 会替换掉所有 $ 开头的变量,导致 $pid 变成空!
$ envsubst < redis.conf.template
port 6379
pidfile /var/run/redis_.pid <-- 糟糕,误伤友军
示例 2:精准注入 (白名单模式)
这是生产环境的最佳实践。只告诉 envsubst 替换哪些变量,忽略原本属于配置文件语法的变量(如 Nginx 的 $host 或 PHP 的 $var)。
# 单引号极其重要!防止 Shell 在命令执行前就解析变量
# 只替换 $REDIS_PORT,放过 $pid
$ envsubst '$REDIS_PORT' < redis.conf.template > redis.conf
# 结果完美:
port 6379
pidfile /var/run/redis_$pid.pid
(注:掌握 envsubst,你的 Docker Entrypoint 脚本将变得前所未有的干净和健壮。)

浙公网安备 33010602011771号