You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Ansible Playbook中的特定任务仅执行一次?

问题描述

为实验室项目编写Ansible Playbook,基于EC2 Ubuntu实例托管网站。安装启用apache2后,/var/www/html/目录会生成默认的index.html文件。编写了删除该文件的任务,用于拉取Git源码前清理目录,首次运行正常,但重复执行Playbook时,该删除任务会导致网站宕机。目前只能在首次运行后注释/删除该任务,尝试过run_once但未成功实现仅执行一次的效果。

Inventory 文件

all:
  hosts:
    webserver:
      ansible_host: 
      ansible_user: 
      ansible_ssh_private_key_file:
    webserver02:
      ansible_host: 
      ansible_user: 
      ansible_ssh_private_key_file: 
    webserver03:
      ansible_host: 
      ansible_user: 
      ansible_ssh_private_key_file:  

  children:
    webservers: 
      hosts: 
        webserver:
        webserver02:
        webserver03:

原 Playbook 代码

- name: Install webserver packages
  hosts: webservers
  become: yes

  tasks:

    - name: Install apache2
      ansible.builtin.apt:
        name: "{{item}}"
        state: latest
        update_cache: yes
      loop:
        - apache2
        - git
        - zip
        - unzip

    - name: Start apache2 service
      ansible.builtin.service:
        name: apache2
        state: started
        enabled: yes

    ### Delete this tasks after running the playbook once ###

    - name: Remove default index.html
      ansible.builtin.file:
        path: /var/www/html/index.html
        state: absent

    - name: Clone the source code
      ansible.builtin.git:
        repo: "{{ gitrepo }}"    ### git source code ###
        dest: "{{ index_html }}" ### /var/www/html   ###
        single_branch: yes
        version: gottoweb
      notify: # the handler will only get executed if there is a change in the git task
        - restart apache2 service

  handlers: # this handler only restarts apache2 when there is a change in the git task
    - name: restart apache2 service
      ansible.builtin.service:
        name: apache2
        state: restarted
        enabled: yes

解决方案

方案1:仅删除Apache默认的index.html

通过检查文件内容特征,判断当前index.html是否为Apache默认页面,仅在匹配时执行删除操作。后续运行时,自定义的index.html不会被误删。

修改后的任务片段:

- name: Start apache2 service
  ansible.builtin.service:
    name: apache2
    state: started
    enabled: yes

# 新增判断逻辑
- name: Check if index.html is Apache default page
  ansible.builtin.command: grep -q "Apache2 Ubuntu Default Page" /var/www/html/index.html
  register: is_default_index
  ignore_errors: yes
  changed_when: false # 标记该任务不会改变系统状态

- name: Remove default index.html (only if it's Apache's default)
  ansible.builtin.file:
    path: /var/www/html/index.html
    state: absent
  when: is_default_index.rc == 0 # 仅当匹配到默认页面内容时执行

- name: Clone the source code
  ansible.builtin.git:
    repo: "{{ gitrepo }}"
    dest: "{{ index_html }}"
    single_branch: yes
    version: gottoweb
  notify:
    - restart apache2 service

方案2:强制Git克隆覆盖默认文件

如果Git仓库包含网站所需的全部文件,可在git任务中添加force: yes参数,强制克隆并覆盖目录内的默认文件,无需单独的删除任务。该方法会清除目录中不在Git仓库内的文件,适合完全由Git管理网站文件的场景。

修改后的Git任务:

- name: Clone the source code (force overwrite existing files)
  ansible.builtin.git:
    repo: "{{ gitrepo }}"
    dest: "{{ index_html }}"
    single_branch: yes
    version: gottoweb
    force: yes
  notify:
    - restart apache2 service

方案3:先拉取Git代码,再清理残留默认文件

调整任务顺序,先执行Git拉取,再检查并删除可能残留的默认index.html。此方法避免了先删除正在使用的自定义文件导致的宕机,但需确保Git仓库能正常克隆到非空目录(或搭配方案2的force参数)。

修改后的任务顺序:

- name: Start apache2 service
  ansible.builtin.service:
    name: apache2
    state: started
    enabled: yes

- name: Clone the source code
  ansible.builtin.git:
    repo: "{{ gitrepo }}"
    dest: "{{ index_html }}"
    single_branch: yes
    version: gottoweb
    force: yes # 可选,用于首次克隆非空目录
  notify:
    - restart apache2 service

- name: Check if index.html is Apache default page
  ansible.builtin.command: grep -q "Apache2 Ubuntu Default Page" /var/www/html/index.html
  register: is_default_index
  ignore_errors: yes
  changed_when: false

- name: Remove leftover default index.html
  ansible.builtin.file:
    path: /var/www/html/index.html
    state: absent
  when: is_default_index.rc == 0

内容的提问来源于stack exchange,提问作者Kyle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:47:06