Ansible单playbook新建服务器执行多操作问题排查
问题核心原因
你的playbook从根上就配错了执行目标:
- 整个play全局配置了
hosts: localhost+connection: local,默认所有任务都会在你运行Ansible的本地机器上执行,根本没有连接到你刚创建的Hetzner云服务器。你看到的can't cd to /home/catena/报错,本质是你本地电脑上不存在这个路径,和你远端服务器上有没有这个目录完全没关系。 - 你用的
action: shell写法本身就是强制在本地执行动作的语法,就算你后面改了主机配置,这种写法也会把任务拉回本地跑,完全不符合你在远端服务器部署文件的需求。 - 你创建完服务器之后,没有把新服务器的IP、SSH连接信息加入Ansible的主机清单,部署任务根本找不到要连接的目标主机。
修正方法
- 把playbook拆成两个独立的play段:第一段在本地执行,负责调用Hetzner API创建云服务器;第二段专门在刚创建的新服务器上执行,负责WordPress部署操作。
- 服务器创建完成后,用
add_host模块把新服务器的IP、SSH登录信息动态加到内存清单里,给后续部署任务用。 - 新服务器启动后先加个SSH连通性检测,等SSH服务就绪了再跑部署任务,避免刚开机连不上报错。
- 废弃
action: shell的写法,直接用shell模块,用模块自带的chdir参数指定工作目录,不要把cd命令拼在执行串里,稳定性更高。 - 提前确认服务器上存在
/home/catena/目录、安装了wget/tar等基础工具、存在www-data用户以及Web运行环境,避免后续命令执行报错。
下面是修正后的参考配置:
--- # 本地执行段:创建云服务器 - name: Create Basic Server hosts: localhost connection: local gather_facts: False vars: hcloud_token: "替换为你的实际Hetzner API token" tasks: - name: Create cloud server hcloud_server: api_token: "{{ hcloud_token }}" name: test-server server_type: cpx31 datacenter: nbg1-dc3 image: "替换为你使用的镜像ID" state: present ssh_keys: - "替换为你要绑定到服务器的SSH密钥名称" register: created_server - name: Add new server to temporary inventory add_host: name: "{{ created_server.hcloud_server.ipv4_address }}" groups: - wp_target ansible_user: root # 替换为服务器实际支持的SSH登录用户 # 远端执行段:部署WordPress - name: Deploy WordPress to new server hosts: wp_target gather_facts: False tasks: - name: Wait for SSH service ready wait_for: port: 22 host: "{{ inventory_hostname }}" delay: 10 timeout: 300 - name: Install required base tools apt: name: - wget - tar state: present update_cache: yes # 如果你用的不是Debian/Ubuntu系镜像,替换为yum/dnf等对应包管理模块 - name: Download and extract WordPress package shell: | wget https://wordpress.org/latest.tar.gz tar xvf latest.tar.gz rm latest.tar.gz chown -R www-data:www-data wordpress args: chdir: /home/catena/ # 如果/home/catena目录不是镜像自带的,提前加file模块任务创建该目录并配置权限 - name: Rename WordPress directory to target site name command: mv /home/catena/wordpress /home/catena/site_name args: chdir: /home/catena/
优化建议
尽量不要写一长串靠&&拼接的shell命令,Ansible原生模块支持幂等、报错信息更清晰,能替代的场景尽量用原生模块:比如下载文件用get_url、解压压缩包用unarchive、改权限/重命名用file模块,比手写shell稳定很多。另外不要把API token这类敏感信息明文写在playbook里,建议用Ansible Vault加密或者从环境变量读取。
内容的提问来源于stack exchange,提问作者Melvin Magro
相关产品推荐
相关产品推荐

