playbook中nginx未启动或端口不监听的主因是服务未启用、配置错误未触发失败、firewalld拦截、模板变量未渲染、发行版差异导致路径/包名错配、半配置状态残留及reload前未校验。

Playbook 中 nginx 服务未启动或端口不监听
常见现象是 Playbook 执行成功,nginx -t 也返回 success,但 curl http://localhost 超时,ss -tlnp | grep :80 没输出。根本原因通常是服务没真正启用,或者配置写错但未触发失败。
- 确保任务中包含
systemctl enable nginx和systemctl start nginx,不能只 reload;Ansible 的service模块默认不启用开机自启,得显式设enabled: yes - 检查
nginx.conf是否被覆盖成空文件或语法错误——用notify触发nginx -t校验再 reload,比直接 restart 更安全 - CentOS/RHEL 8+ 默认用
firewalld,得加任务放行http服务,否则即使 nginx 在跑,外部也连不上
用 ansible.builtin.template 渲染 nginx 配置时变量失效
比如想把 server_name 设为动态主机名,模板里写了 {{ ansible_hostname }},但生成的配置仍是字面量 {{ ansible_hostname }},说明变量没解析。
- 确认模板文件后缀是
.j2(如default.conf.j2),且template模块路径指向它,不是直接 copy 原文件 - 检查任务中是否误用了
copy模块——只有template模块才做 Jinja2 渲染;copy加content:或src:都不会展开变量 - 若变量来自 inventory,确认作用域:host_vars 下的变量对单台生效,group_vars 需匹配主机组名;调试可用
debug: var=ansible_hostname看值是否为空
不同发行版安装 nginx 包名和路径不一致
Debian/Ubuntu 用 nginx-full 或 nginx-light,RHEL/CentOS 用 nginx,Alpine 用 nginx 但配置路径在 /etc/nginx/conf.d/,而有些旧版 CentOS 把默认站点配在 /etc/nginx/nginx.conf 里——混用会导致部署后 404 或 502。
- 用
ansible_facts['distribution']和ansible_facts['distribution_major_version']做条件判断,分发不同包名和配置路径 - 避免硬编码
/usr/share/nginx/html:用nginx_docroot变量统一定义,并在各发行版 vars 文件里赋值 - 安装后执行
nginx -V 2>&1 | grep "prefix"获取实际安装路径,比查文档更可靠
playbook 执行中途失败导致 nginx 处于半配置状态
比如证书文件拷贝失败,但前面的配置已写入、服务已 reload,此时 nginx 可能因找不到证书而拒绝启动,后续重跑又跳过已存在的文件,问题卡住。
- 给关键任务加
ignore_errors: no(默认就是),别手滑写成yes;尤其copy证书、template配置、command: nginx -t这三步必须严格失败中断 - 用
check_mode: no显式关闭校验模式,防止某些模块(如file)在 check 模式下不报错但实际缺失权限 - 上线前先在测试机跑一遍
ansible-playbook site.yml --check,但注意--check不会执行command或shell,得单独验证nginx -t这类命令
最麻烦的是配置热加载和证书更新之间的竞态——reload 前没校验,reload 后才发现证书格式错,服务就挂了。所以 nginx -t 必须放在 reload 之前,且作为独立任务,失败就停住。











