如何使用先前任务中定义的变量用于条件省略该主机的任务?

How to use a variable defined in a previous task for use in a task where the conditional omits that host?

实际上,我有两台服务器,我试图从其中一台的命令中获取使用输出,以配置另一台,反之亦然。我花了几个小时阅读这篇文章,发现 hostvars 进程和虚拟主机似乎是我想要的。无论我如何尝试实施此过程,我仍然会收到未定义的变量,and/or 来自主机的失败不在任务的模式中:

这是相关块,只有主机 mux-ds1mux-ds2dispatchers 组中:

---
 - name: Play that sets up the sql database during the build process on all mux dispatchers.
   hosts: mux_dispatchers
   remote_user: ansible
   vars:
     ansible_ssh_pipelining: yes

   tasks:

     - name: Check and save database master bin log file and position on mux-ds2.
       shell: sudo /usr/bin/mysql mysql -e "show master status \G" | grep -E 'File:|Position:' | cut -d{{':'}} -f2 | awk '{print }'
       become: yes
       become_method: sudo
       register: syncds2
       when: ( inventory_hostname == 'mux-ds2' )

     - name: Print current ds2 database master bin log file.
       debug:
         var: "syncds2.stdout_lines[0]"

     - name: Print current ds2 database master bin position.
       debug:
         var: "syncds2.stdout_lines[1]"

     - name: Add mux-ds2 some variables to a dummy host allowing us to use these variables on mux-ds1.
       add_host:
         name: "ds2_bin"
         bin_20: "{{ syncds2.stdout_lines }}"

     - debug:
         var: "{{ hostvars['ds2_bin']['bin_21'] }}"

     - name: Compare master bin variable output for ds1's database and if different, configure for it.
       shell: sudo /usr/bin/mysql mysql -e "stop slave; change master to master_log_file='"{{ hostvars['ds2_bin']['bin_21'][0] }}"', master_log_pos="{{ hostvars['ds2_bin']['bin_21'][1] }}"; start slave"
       become: yes
       become_method: sudo
       register: syncds1
       when: ( inventory_hostname == 'mux-ds1' )

基本上一切正常,直到我尝试使用调试模块从虚拟主机查看变量的值,但它告诉我该变量仍然未定义,即使它已在原始变量中定义。这应该是解决此类问题的系统:

TASK [Print current ds2 database master bin log file.] **************************************************
ok: [mux-ds1] => {
    "syncds2.stdout_lines[0]": "VARIABLE IS NOT DEFINED!"
}
ok: [mux-ds2] => {
    "syncds2.stdout_lines[0]": "mysql-bin.000001"
}

TASK [Print current ds2 database master bin position.] **************************************************
ok: [mux-ds1] => {
    "syncds2.stdout_lines[1]": "VARIABLE IS NOT DEFINED!"
}
ok: [mux-ds2] => {
    "syncds2.stdout_lines[1]": "107"
}

上面的工作如我所愿,并且为 mux-ds2.

正确填充和引用了变量
TASK [Add mux-ds2 some variables to a dummy host allowing us to use these variables on mux-ds1.] ********
fatal: [mux-ds1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout_lines'\n\nThe error appears to be in '/home/ansible/ssn-project/playbooks/i_mux-sql-config.yml': line 143, column 8, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n     - name: Add mux-ds2 some variables to a dummy host allowing us to use these variables on mux-ds1.\n       ^ here\n"}

这就是问题所在,变量似乎再次神奇地未定义,考虑到此过程旨在结束 -运行 这个问题,这很奇怪。我什至无法完成第二组调试任务。

请注意,这最终是为了同步两个 master/master 复制 mysql 数据库。我也是用 shell 模块做的,因为必须使用的 mysql 版本不能高于 5.8,而 ansible 模块需要 5.9,这是一个耻辱。 mux-ds2 将以相反的方式完成相同的过程,假设这可以正常工作。

要么我在这个实现中犯了一个错误,导致它无法运行,要么我使用了错误的实现来实现我想要的。我现在花了太多时间试图独自解决这个问题,并且会很感激任何可行的解决方案。提前致谢!

simple delegation of tasks and the usage of the special variable hostvars 能够从不同的节点获取事实时,您似乎正在走一条复杂的路线,应该会给您期望的结果。

这是一个例子——只关注重要的部分——所以,你可能想在里面添加 becomebecome_user

- shell: >-
    sudo /usr/bin/mysql mysql -e "show master status \G" 
    | grep -E 'File:|Position:' 
    | cut -d{{':'}} -f2 
    | awk '{print }'
  delegate_to: mux-ds2
  run_once: true
  register: syncds2

- shell: >-
    sudo /usr/bin/mysql mysql -e "stop slave; 
      change master to 
      master_log_file='"{{ hostvars['mux-ds2'].syncds2.stdout_lines.0 }}"', 
      master_log_pos="{{ hostvars['mux-ds2'].syncds2.stdout_lines.1 }}"; 
      start slave"
  delegate_to: mux-ds1
  run_once: true

这是一个示例,运行 一些虚拟 shell 任务,给定剧本:

- hosts: node1, node2
  gather_facts: no

  tasks:
    - shell: |
        echo 'line 0'
        echo 'line 1'
      delegate_to: node2
      run_once: true
      register: master_config

    - shell: |
        echo '{{ hostvars.node2.master_config.stdout_lines.0 }}'
        echo '{{ hostvars.node2.master_config.stdout_lines.1 }}'
      delegate_to: node1
      run_once: true
      register: master_replicate_config

    - debug:
        var: master_replicate_config.stdout_lines
      delegate_to: node1
      run_once: true

这将产生:

PLAY [node1, node2] **********************************************************

TASK [shell] *****************************************************************
changed: [node1 -> node2(None)]

TASK [shell] *****************************************************************
changed: [node1]

TASK [debug] *****************************************************************
ok: [node1] => 
  master_replicate_config.stdout_lines:
  - line 0
  - line 1