最近在使用 Confd 管理配置的过程中,发现很多文章都使用了错误的 check_cmd
配置。
检查 Confd 生成的临时文件
例如,有人使用了这样的配置:
# ...
dest = "/etc/nginx/nginx.conf"
check_cmd = "/usr/sbin/nginx -t"
Confd 会在写入目标文件前,执行 check_cmd
配置的命令进行检查,但是 nginx -t
并不能检测到刚刚生成的临时文件。会导致以下情况:
- 如果 Nginx 的当前文件包含了错误,那么检查永远不通过;也就意味着 Confd 生成了正确的文件也不会生效,除非手动干预来修正 Nginx 当前文件中的错误。
- 如果 Nginx 的当前文件不包含错误,那么检查肯定是通过的;也就意味着即使 Confd 生成了错误的文件,也会写入到目标文件中;下一次生成配置文件时,会导致情况 1 发生。
所以正确的写法应该是:
dest = "/etc/nginx/nginx.conf"
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"
{.src}
就是 Confd 生成的最新文件的临时路径,与 dest
在相同目录,比如可能是 /etc/nginx/.nginx.conf123456789
(123456789 是一个随机的数字)。
目标非 /etc/nginx/nginx.conf
的情况
如果 dest
是一个被 Nginx include 的文件,会发生什么呢?
# ...
dest = "/etc/nginx/conf.d/proxy.conf"
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"
假设最终生成的 proxy.conf 内容是:
upstream a {
server 192.168.1.1;
}
server{
listen 80;
server_name _;
location /{
proxy_pass http://a;
}
}
最终执行的检查命令可能是:
/usr/sbin/nginx -t -c /etc/nginx/conf.d/.proxy.conf123456789
不出意外,还是永远检查失败。因为检查时把 -c
的参数当作是唯一的配置文件,配置文件里并没有 http
;如果还用了 include
,那么多半还会提示找不到文件错误。
这里存在两个问题,一是配置文件不完整,二是相对路径有错。
所以合理的做法应该是:为 .proxy.conf123456789
补充缺失的语句,并复制到 /etc/nginx
,然后再调用 nginx -t -c /etc/nginx/.proxy.conf123456789
。
下面是一个经过验证的正确工作的例子:
check_cmd = "TMP=/etc/nginx/$(basename {{.src}}).tmp && echo 'events{}http{' > $TMP && cat {{.src}} >> $TMP && echo '}' >> $TMP && (nginx -t -c $TMP; R=$?; rm -f $TMP; exit $R)"
具体过程是,将 /etc/nginx/conf.d/.proxy.conf123456789
用 events{}http{
和 }
包裹,输出到 /etc/nginx/.proxy.conf123456789.tmp
中,校验后删除这个临时文件。
Webmention
评论表单