角色中定义的Ansible处理程序是否在整个剧本或角色之后执行?


13

我正在运行Ansible 2.0,我可以运行它,但是我也可能被欺骗,以至于我的经验测试认为这是不正确的,并且找不到任何文档可以告诉我何时应该运行处理程序。

如果处理程序没有在任务结束时运行,这就是我的难题。我有一个包含5个角色的剧本,我想在末尾添加6个角色,该角色需要先完成第4个角色的处理程序才能开始。

有什么方法可以运行Ansible来依靠完成的处理程序(即角色完全完成)再执行其他操作,或者我使用的处理程序错误吗?

Answers:


17

处理程序执行:

  • 剧本结尾(不是剧本)
  • 在执行meta: flush_handlers任务时

因此,“ 需要在第6角色的末尾添加第4角色的处理程序 ”,您需要:

  • 将角色分配分为多个单独的角色;
  • 或添加一个meta任务,并在include_role模块中包含第6个角色:

    roles:
      - role4
    tasks:
      - meta: flush_handlers
      - include_role:
          name: role6
    

对于您的用例,我建议第一种方法,因为该include_role模块仍然非常新鲜,并且在使用它时会出现一些古怪的现象(请参阅SO上的此问题)。


此外,请注意,处理程序的名称和侦听调用是全局的,因此,如果两个角色在单独的角色中具有相同的名称,并且两个角色均在一次播放中分配,则它们将发生冲突。(请参阅处理程序:更改时运行操作

处理程序[]由全局唯一名称引用,并由通知程序通知。[]处理程序,在特定播放中完成所有任务后,它将仅运行一次。

处理程序名称和侦听主题位于全局命名空间中。


  • 经验证明(运行此shell脚本以确认处理程序在播放结束时执行-此处存在矛盾的注释和答案):

    #!/bin/bash
    
    mkdir -p ./sf831880/roles/role1
    mkdir -p ./sf831880/roles/role1/handlers
    mkdir -p ./sf831880/roles/role1/tasks
    mkdir -p ./sf831880/roles/role2
    mkdir -p ./sf831880/roles/role2/handlers
    mkdir -p ./sf831880/roles/role2/tasks
    
    cat >./sf831880/roles/role1/tasks/main.yml <<TASKS1_END
    ---
    - name: Always true in role1
      command: echo role1
      notify: handler1
    TASKS1_END
    
    cat >./sf831880/roles/role2/tasks/main.yml <<TASKS2_END
    ---
    - name: Always true in role2
      command: echo role2
      notify: handler2
    TASKS2_END
    
    cat >./sf831880/roles/role1/handlers/main.yml <<HANDLERS1_END
    ---
    - name: handler1
      debug:
        msg: "This is a handler in role1"
    HANDLERS1_END
    
    cat >./sf831880/roles/role2/handlers/main.yml <<HANDLERS2_END
    ---
    - name: handler2
      debug:
        msg: "This is a handler in role2"
    HANDLERS2_END
    
    cat >./sf831880/playbook.yml <<PLAYBOOK_END
    ---
    - hosts: localhost
      gather_facts: no
      connection: local
      roles:
        - role1
        - role2
      tasks:
        - debug:
            msg: "This is a task in a play"
    PLAYBOOK_END
    
    ansible-playbook ./sf831880/playbook.yml
    

    结果:

    PLAY [localhost] ***************************************************************
    
    TASK [role1 : Always true in role1] ********************************************
    changed: [localhost]
    
    TASK [role2 : Always true in role2] ********************************************
    changed: [localhost]
    
    TASK [debug] *******************************************************************
    ok: [localhost] => {
        "msg": "This is a task in a play"
    }
    
    RUNNING HANDLER [role1 : handler1] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role1"
    }
    
    RUNNING HANDLER [role2 : handler2] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role2"
    
  • 播放已修改为包含meta: flush_handlers

    ---
    - hosts: localhost
      gather_facts: no
      connection: local
      roles:
        - role1
        - role2
      tasks:
        - meta: flush_handlers
        - debug:
            msg: "This is a task in a play"
    

    结果:

    PLAY [localhost] ***************************************************************
    
    TASK [role1 : Always true in role1] ********************************************
    changed: [localhost]
    
    TASK [role2 : Always true in role2] ********************************************
    changed: [localhost]
    
    RUNNING HANDLER [role1 : handler1] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role1"
    }
    
    RUNNING HANDLER [role2 : handler2] *********************************************
    ok: [localhost] => {
        "msg": "This is a handler in role2"
    }
    
    TASK [debug] *******************************************************************
    ok: [localhost] => {
        "msg": "This is a task in a play"
    

2

处理程序是任务列表,实际上与常规任务没有什么不同,它们由全局唯一名称引用,并由通知者通知。如果没有任何通知处理程序,它将不会运行。无论有多少任务通知处理程序,在特定播放中完成所有任务后,该处理程序将仅运行一次。Ansible文档

1)执行相同操作的处理程序应命名为相同。
restart nginx始终重新启动nginx的,不handler1handler2

2)处理程序在整个“播放”的结尾处运行,该播放以您的小节为范围。

3)对于应该重新启动的任务,我将使用registerwhen函数,请注意此var应该随身携带。

代码源

PLAY [localhost] ***************************************************************

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "Play 1"
}

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role2 : Run if change in task c of role 1] *******************************
changed: [localhost]

TASK [role2 : Always true in role2] ********************************************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "This is a task in a play"
}

RUNNING HANDLER [role1 : handler] **********************************************
ok: [localhost] => {
    "msg": "This is a handler in role1"
}

PLAY [localhost] ***************************************************************

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "Play 2"
}

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role1 : Always true in role1] ********************************************
changed: [localhost]

TASK [role2 : Run if change in task c of role 1] *******************************
changed: [localhost]

TASK [role2 : Always true in role2] ********************************************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "This is a task in a play"
}

RUNNING HANDLER [role1 : handler] **********************************************
ok: [localhost] => {
    "msg": "This is a handler in role1"
}

PLAY RECAP *********************************************************************
localhost                  : ok=20   changed=14   unreachable=0    failed=0

完成相同任务的方法很多。处理程序旨在防止多次重新启动同一进程,例如对具有网站,ssl证书和需要重新启动服务的其他任务的nginx服务器进行多次更改。


您引用“ 在特定任务中完成所有任务后仅运行一次 ”,然后声明完全不同的内容“ 在每个角色结束时运行任务 ”。您的主张也与现实不同。
techraf

不,您会误会,如果我从meta调用服务器角色的同一个处理程序4次。它只运行一次
Jacob

问题很明确:处理程序何时运行?他们没有运行多少次。他们是在戏曲的结尾而不是角色的结尾运行的。期。您是第三人称,否则,即使您在我发布答案并举例说明此说法为假之后也这样做了。
techraf

我的回答是,对于必须在其角色中重新启动的项目,请使用任务而不是处理程序。
雅各布·埃文斯

@techraf你在那里。
雅各布·埃文斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.