这个问题没有答案。有人提到环境变量。能详细说明一下吗?
这看起来是一个简单的问题,但在 ansible 中却不是。它不断出现。特别是在错误情况下。 我需要一个全局变量。我可以在处理一台主机播放时设置一个,然后稍后与另一台主机进行检查。简而言之,这样我就可以根据变量在剧本中稍后进行分支。
我们无法控制自定义软件的安装,但如果安装了,我们就必须将不同的软件放在其他机器上。最重要的是,安装会根据虚拟机文件夹的不同而有所不同。我的全球变体王国。
变量的范围仅与当前 ansible_hostname 相关。是的,我们将 group_vars/all.yml 作为全局变量,但我们无法在游戏中设置它们。如果我设置一个变量,其他主机的播放/任务就看不到它。我了解变量的范围,但我想设置一个可以在所有剧本播放中读取的全局变量。 实际实现并不重要,但变量访问很(重要)。
我的问题:有没有办法设置一个变量,以便在另一台主机上运行不同的任务时可以检查该变量?像 setGlobalSpaceVar(myvar, true) 这样的东西?我知道没有这样的方法,但我正在寻找解决方法。改写:在一个主机的一个任务中设置一个变量,然后在另一台主机的另一个任务中读取该变量。
我能想到的唯一方法是更改控制器上的文件,但这似乎是假的。
一个例子
以下内容涉及 Oracle 备份和本地可执行文件,但我将其保持通用。对于下面的内容 - 是的,我可以执行 run_once,但这不能回答我的问题。 这个变量访问问题在不同的上下文中不断出现。
我有 4 个 xyz 服务器。我有 2 个程序需要执行,但只在两台不同的机器上执行。我不知道是哪一个。对于不同的虚拟机环境,设置可能会有所不同。
我们的programOne在具有驱动器E的服务器上运行。我可以使用ansible找到哪个服务器具有驱动器E,并在每次设置变量(driveE_machine)时进行相应的播放。它仅适用于该主机。为此,其他 3 台机器不会设置driveE_machine。 在稍后的游戏中,我需要仅在其他 3 台机器中的一台上执行另一个程序。这意味着我需要设置一个变量,该变量可以被未运行第二个程序的其他两台主机读取。 我不知道该怎么做。
库存档案:
[xyz]
serverxyz[1:4].private.mystuff
剧本示例:
---
- name: stackoverflow variable question
hosts: xyz
gather_facts: no
serial: 1
tasks:
- name: find out who has drive E
win_shell: dir e:\
register: adminPage
ignore_errors: true
# This sets a variable that can only be read for that host
- name: set fact driveE_machine when rc is 0
set_fact:
driveE_machine: "{{inventory_hostname}}"
when: adminPage.rc == 0
- name: run program 1
include: tasks/program1.yml
when: driveE_machine is defined
# program2.yml executes program2 and needs to set some kind of variable
# so this include can only be executed once for the other 3 machines
# (not one that has driveE_machine defined and ???
- name: run program 2
include: tasks/program2.yml
when: driveE_machine is undefined and ???
# please don't say run_once: true - that won't solve my variable access question
有没有办法设置一个变量,以便在另一台主机上运行任务时可以检查该变量?
不确定你真正想要什么,但你可以使用单个循环任务为游戏中的每个主机设置一个事实(全局变量的一些模拟):
playbook.yml
---
- hosts: mytest
gather_facts: no
vars:
tasks:
# Set myvar fact for every host in a play
- set_fact:
myvar: "{{ inventory_hostname }}"
delegate_to: "{{ item }}"
with_items: "{{ play_hosts }}"
run_once: yes
# Ensure that myvar is a name of the first host
- debug:
msg: "{{ myvar }}"
主持人
[mytest]
aaa ansible_connection=local
bbb ansible_connection=local
ccc ansible_connection=local
结果
PLAY [mytest] ******************
META: ran handlers
TASK [set_fact] ******************
ok: [aaa -> aaa] => (item=aaa) => {"ansible_facts": {"myvar": "aaa"}, "ansible_facts_cacheable": false, "changed": false, "failed": false, "item": "aaa"}
ok: [aaa -> bbb] => (item=bbb) => {"ansible_facts": {"myvar": "aaa"}, "ansible_facts_cacheable": false, "changed": false, "failed": false, "item": "bbb"}
ok: [aaa -> ccc] => (item=ccc) => {"ansible_facts": {"myvar": "aaa"}, "ansible_facts_cacheable": false, "changed": false, "failed": false, "item": "ccc"}
TASK [debug] ******************
ok: [aaa] => {
"msg": "aaa"
}
ok: [bbb] => {
"msg": "aaa"
}
ok: [ccc] => {
"msg": "aaa"
}
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#fact-caching
如文档中其他地方所示,一台服务器可以引用另一台服务器的变量,如下所示:
{{ hostvars['asdf.example.com']['ansible_os_family'] }}
这甚至适用于在剧本中动态设置的变量。
这个答案并不预先假设您的主机名,也不预先假设有多少主机有“驱动器 E:”。它将选择第一个可访问且具有“驱动器 E:”的驱动器。我没有 Windows 盒子,所以我通过随机抛硬币来判断主机是否这样做;你当然可以使用你原来的
win_shell
任务,我已经注释掉了。
---
- hosts: all
gather_facts: no
# serial: 1
tasks:
# - name: find out who has drive E
# win_shell: dir e:\
# register: adminPage
# ignore_errors: true
- name: "Fake finding hosts with drive E:."
# I don't have hosts with "drive E:", so fake it.
shell: |
if [ $RANDOM -gt 10000 ] ; then
exit 1
else
exit 0
fi
args:
executable: /bin/bash
register: adminPage
failed_when: false
ignore_errors: true
- name: "Dict of hosts with E: drives."
run_once: yes
set_fact:
driveE_status: "{{ dict(ansible_play_hosts_all |
zip(ansible_play_hosts_all |
map('extract', hostvars, ['adminPage', 'rc'] ) | list
))
}}"
- name: "List of hosts with E: drives."
run_once: yes
set_fact:
driveE_havers: "{%- set foo=[] -%}
{%- for dE_s in driveE_status -%}
{%- if driveE_status[dE_s] == 0 -%}
{%- set _ = foo.append( dE_s ) -%}
{%- endif -%}
{%- endfor -%}{{ foo|list }}"
- name: "First host with an E: drive."
run_once: yes
set_fact:
driveE_first: "{%- set foo=[] -%}
{%- for dE_s in driveE_status -%}
{%- if driveE_status[dE_s] == 0 -%}
{%- set _ = foo.append( dE_s ) -%}
{%- endif -%}
{%- endfor -%}{{ foo|list|first }}"
- name: Show me.
run_once: yes
debug:
msg:
- "driveE_status: {{ driveE_status }}"
- "driveE_havers: {{ driveE_havers }}"
- "driveE_first: {{ driveE_first }}"
我采取了不同的方法:
以下是在所有主机上设置相同生成密码的示例:
- name: Generate a password
set_fact:
configure_user_password: "{{
lookup(
'ansible.builtin.password',
'/dev/null',
chars=[
'ascii_letters',
'digits'
],
length=12
)
}}"
- debug:
var: configure_user_password
- name: Synchronize generated passwords
set_fact:
configure_user_password: "{{
(
hostvars
| dict2items
| selectattr(
'value.configure_user_password',
'defined'
)
| map(attribute='value.configure_user_password')
| list
)
[0]
}}"
- debug:
var: configure_user_password
这对我有用,你可以直接使用register var,不需要使用set_fact。
---
- hosts: manager
tasks:
- name: dir name
shell: cd /tmp && pwd
register: homedir
when: "'manager' in group_names"
- hosts: all
tasks:
- name: create a test file
shell: touch "{{hostvars['manager.example.io'['homedir'].stdout}}/t1.txt"
我在ansible任务提示菜单中使用了“set_fact”模块,这有助于将用户输入传递到所有清单主机中。
#监控手册 - 主持人:全部 收集事实:是的 变成:是 任务: - 暂停: 迅速的: ” 您想要执行哪种监控? -------------------------------------- 1.内存利用率: 2.CPU利用率: 3. 文件系统实用程序 化: 4. 从 Playbook 中存在: 5. 获取Nmon报告 请选择选项: -------------------------------------- ” 注册:菜单 - 设置事实: 选项:“{{menu.user_input}}” delegate_to:“{{项目}}” with_items:“{{ play_hosts }}” 运行一次:是的 #1 内存监控 - 暂停: 迅速的: ” -------------------------------------- 输入监控事件编号 = " 注册:事件_编号_结果 当:选项==“1” - 名称:标准化 event_number 变量 设置事实: Incident_number:“{{ Incident_number_result.user_input }}” 当:选项==“1” delegate_to:“{{项目}}” with_items:“{{ play_hosts }}” 运行一次:是的
ansible 剧本结果是
[ansibusr@ansiblemaster monitoring]$ ansible-playbook monitoring.yml
PLAY [all] **************************************************************************
TASK [Gathering Facts] **************************************************************************
ok: [node2]
ok: [node1]
[pause]
Which monitoring you want to perform?
--------------------------------------
1. Memory Utilization:
2. CPU Utilization:
3. Filesystem Utilization:
4. Exist from Playbook:
5. Fetch Nmon Report
Please select option:
--------------------------------------
:
TASK [pause] **************************************************************************
ok: [node1]
TASK [set_fact] **************************************************************************
ok: [node1 -> node1] => (item=node1)
ok: [node1 -> node2] => (item=node2)
[pause]
--------------------------------------
Enter monitoring Incident Number = :
INC123456
TASK [pause] **************************************************************************
ok: [node1]
TASK [Standardize incident_number variable] ****************************************************************************************************************************
ok: [node1 -> node1] => (item=node1)
ok: [node1 -> node2] => (item=node2)