如何使用单独的变量保存不同主机的 return 值
How to save the return values of different hosts with separate variables
这是我的剧本:
---
- hosts: server
gather_facts: false
tasks:
- name:
shell: ping -c 1 -W 1 <ip_addr>
register: shell_result_var
- name:
set_fact:
time_fact: "{{ ((shell_result_var['stdout_lines'][1] | split('='))[3] | split(' '))[0] }}"
执行ansible-playbook playbook.yml -vvv
TASK [set_fact] **************************************************************************************************************************************************************
task path: /home/playbook.yml:9
ok: [*.*.*.*] => {"ansible_facts": {"time_fact": "56.9"}, "changed": false}
ok: [*.*.*.*] => {"ansible_facts": {"time_fact": "32.1"}, "changed": false}
META: ran handlers
META: ran handlers
我想把这两个字符串("56.9" 和 "32.1" )保存在不同的变量中,然后将它们转换成数字来计算它们
I want to save these two strings("56.9" and "32.1" ) in different variables and convert them into numbers to calculate them
ping 命令的输出是一个浮点数,所以我就这样对待它。我添加了一个例子,所以你可以用它来进行计算。
- hosts:
- test-multi-01
gather_facts: false
tasks:
- name:
shell: 'ping -c 1 -W 1 <ip> | grep -Po "time=.*"'
register: shell_result_var
- set_fact:
ping_number: "{{ shell_result_var.stdout | regex_replace(' ms','') | regex_replace('time=','') | float }}"
- debug:
msg: "{{ ping_number | float + 0.1 }}"
生产:
ok: [test-multi-01] => {
"msg": "0.33499999999999996"
}
您可以使用特殊变量hostvars访问每个主机的变量。例如,使用 run_once
然后,您可以 运行 在 ansible provisioner 上一次性执行您想要的“计算操作”。
- hosts: server
name:
become: no
gather_facts: false
tasks:
- name: Test reachability to 1.1.1.1
ansible.builtin.shell: ping -c 1 -W 1 1.1.1.1 | grep --only-matching "time=.*"
register: ping_result
- name: extract time from ping output
ansible.builtin.set_fact:
ping_number: "{{ ping_result.stdout | regex_replace(' ms','') | regex_replace('time=','') | float }}"
- name: debug ping time of each host
ansible.builtin.debug:
var: ping_number
- name: set total ping time once for all hosts
ansible.builtin.set_fact:
total: "{{ total | default(0.0) | float + hostvars[item].ping_number | float }}"
loop: "{{ ansible_play_hosts }}"
run_once: true
- name: set average ping time once for all hosts
ansible.builtin.set_fact:
average_ping_time: "{{ total|float / ansible_play_hosts|length }}"
run_once: true
- name: debug total ping time
ansible.builtin.debug:
var: total
run_once: true
- name: debug average ping time
ansible.builtin.debug:
var: average_ping_time
run_once: true
PLAY [] ***************************************************************************************************
TASK [Test reachability to 1.1.1.1] ********************************************************************************************************************
Tuesday 28 December 2021 13:28:11 +0000 (0:00:00.028) 0:00:00.028 ******
changed: [host1]
changed: [host2]
TASK [gather time as float] ****************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.705) 0:00:00.733 ******
ok: [host1]
ok: [host2]
TASK [print individual time] ***************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.083) 0:00:00.817 ******
ok: [host1] =>
ping_number: '1.71'
ok: [host2] =>
ping_number: '3.89'
TASK [gather] ******************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.100) 0:00:00.917 ******
ok: [host1 -> localhost] => (item=host1)
ok: [host1 -> localhost] => (item=host2)
TASK [do something] ************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.042) 0:00:00.960 ******
ok: [host1 -> localhost]
TASK [do something] ************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.022) 0:00:00.983 ******
ok: [host1 -> localhost] =>
total: '5.6'
TASK [do something] ************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.022) 0:00:01.005 ******
ok: [host1 -> localhost] =>
average_ping_time: '2.8'
PLAY RECAP *********************************************************************************************************************************************
host1 : ok=7 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
根据你的问题和不同的评论,我不太确定你想计算什么。所以这是一个非常基本的例子,得到所有主机的总和和平均值。
您可以查看 jinja2 filter and ansible filters 的文档,了解有关我在剧本中使用的表达式的更多信息。
请注意,jinja2 输出字符串,因此传递给 set_fact
的值会转换回字符串。因此,在剧本的不同点使用大量 float
过滤器并不是过度谨慎,而是绝对必要的。
我使用以下两台主机的“假”清单 ìnv.yml
都解析到我的本地计算机。
---
all:
vars:
ansible_connection: local
hosts:
test1:
test2:
以及 test.yml
剧本:
---
- hosts: all
gather_facts: false
tasks:
- name: Run ping command
shell: ping -c 1 -W 1 192.168.0.2
register: ping_cmd
changed_when: false
- name: set ping time for each host
set_fact:
ping_time: "{{ ((ping_cmd.stdout_lines[1] | split('='))[3] | split(' '))[0] }}"
- name: set total ping time once for all hosts
set_fact:
total_ping_time: "{{ play_hosts | map('extract', hostvars)
| map(attribute='ping_time') | map('float') | sum }}"
run_once: true
- name: set mean ping time once for all hosts
set_fact:
mean_ping_time: "{{ ((total_ping_time | float) / (play_hosts | length)) }}"
run_once: true
- name: show the result
debug:
msg: "For this host, ping_time is {{ ping_time }}s
for a total of {{ total_ping_time | float | round(3) }}s
and an average of {{ mean_ping_time | float | round(3) }}s"
给出:
$ ansible-playbook -i inv.yml test.yml
PLAY [all] ********************************************************************************************************************************************************************************************************
TASK [Run ping command] *******************************************************************************************************************************************************************************************
ok: [test1]
ok: [test2]
TASK [set ping time for each host] ********************************************************************************************************************************************************************************
ok: [test1]
ok: [test2]
TASK [set total ping time once for all hosts] *********************************************************************************************************************************************************************
ok: [test1]
TASK [set mean ping time once for all hosts] **********************************************************************************************************************************************************************
ok: [test1]
TASK [show the result] ********************************************************************************************************************************************************************************************
ok: [test1] => {
"msg": "For this host, ping_time is 0.137s for a total of 0.214s and an average of 0.107s"
}
ok: [test2] => {
"msg": "For this host, ping_time is 0.077s for a total of 0.214s and an average of 0.107s"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
test1 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test2 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这是我的剧本:
---
- hosts: server
gather_facts: false
tasks:
- name:
shell: ping -c 1 -W 1 <ip_addr>
register: shell_result_var
- name:
set_fact:
time_fact: "{{ ((shell_result_var['stdout_lines'][1] | split('='))[3] | split(' '))[0] }}"
执行ansible-playbook playbook.yml -vvv
TASK [set_fact] **************************************************************************************************************************************************************
task path: /home/playbook.yml:9
ok: [*.*.*.*] => {"ansible_facts": {"time_fact": "56.9"}, "changed": false}
ok: [*.*.*.*] => {"ansible_facts": {"time_fact": "32.1"}, "changed": false}
META: ran handlers
META: ran handlers
我想把这两个字符串("56.9" 和 "32.1" )保存在不同的变量中,然后将它们转换成数字来计算它们
I want to save these two strings("56.9" and "32.1" ) in different variables and convert them into numbers to calculate them
ping 命令的输出是一个浮点数,所以我就这样对待它。我添加了一个例子,所以你可以用它来进行计算。
- hosts:
- test-multi-01
gather_facts: false
tasks:
- name:
shell: 'ping -c 1 -W 1 <ip> | grep -Po "time=.*"'
register: shell_result_var
- set_fact:
ping_number: "{{ shell_result_var.stdout | regex_replace(' ms','') | regex_replace('time=','') | float }}"
- debug:
msg: "{{ ping_number | float + 0.1 }}"
生产:
ok: [test-multi-01] => {
"msg": "0.33499999999999996"
}
您可以使用特殊变量hostvars访问每个主机的变量。例如,使用 run_once
然后,您可以 运行 在 ansible provisioner 上一次性执行您想要的“计算操作”。
- hosts: server
name:
become: no
gather_facts: false
tasks:
- name: Test reachability to 1.1.1.1
ansible.builtin.shell: ping -c 1 -W 1 1.1.1.1 | grep --only-matching "time=.*"
register: ping_result
- name: extract time from ping output
ansible.builtin.set_fact:
ping_number: "{{ ping_result.stdout | regex_replace(' ms','') | regex_replace('time=','') | float }}"
- name: debug ping time of each host
ansible.builtin.debug:
var: ping_number
- name: set total ping time once for all hosts
ansible.builtin.set_fact:
total: "{{ total | default(0.0) | float + hostvars[item].ping_number | float }}"
loop: "{{ ansible_play_hosts }}"
run_once: true
- name: set average ping time once for all hosts
ansible.builtin.set_fact:
average_ping_time: "{{ total|float / ansible_play_hosts|length }}"
run_once: true
- name: debug total ping time
ansible.builtin.debug:
var: total
run_once: true
- name: debug average ping time
ansible.builtin.debug:
var: average_ping_time
run_once: true
PLAY [] ***************************************************************************************************
TASK [Test reachability to 1.1.1.1] ********************************************************************************************************************
Tuesday 28 December 2021 13:28:11 +0000 (0:00:00.028) 0:00:00.028 ******
changed: [host1]
changed: [host2]
TASK [gather time as float] ****************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.705) 0:00:00.733 ******
ok: [host1]
ok: [host2]
TASK [print individual time] ***************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.083) 0:00:00.817 ******
ok: [host1] =>
ping_number: '1.71'
ok: [host2] =>
ping_number: '3.89'
TASK [gather] ******************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.100) 0:00:00.917 ******
ok: [host1 -> localhost] => (item=host1)
ok: [host1 -> localhost] => (item=host2)
TASK [do something] ************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.042) 0:00:00.960 ******
ok: [host1 -> localhost]
TASK [do something] ************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.022) 0:00:00.983 ******
ok: [host1 -> localhost] =>
total: '5.6'
TASK [do something] ************************************************************************************************************************************
Tuesday 28 December 2021 13:28:12 +0000 (0:00:00.022) 0:00:01.005 ******
ok: [host1 -> localhost] =>
average_ping_time: '2.8'
PLAY RECAP *********************************************************************************************************************************************
host1 : ok=7 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
根据你的问题和不同的评论,我不太确定你想计算什么。所以这是一个非常基本的例子,得到所有主机的总和和平均值。
您可以查看 jinja2 filter and ansible filters 的文档,了解有关我在剧本中使用的表达式的更多信息。
请注意,jinja2 输出字符串,因此传递给 set_fact
的值会转换回字符串。因此,在剧本的不同点使用大量 float
过滤器并不是过度谨慎,而是绝对必要的。
我使用以下两台主机的“假”清单 ìnv.yml
都解析到我的本地计算机。
---
all:
vars:
ansible_connection: local
hosts:
test1:
test2:
以及 test.yml
剧本:
---
- hosts: all
gather_facts: false
tasks:
- name: Run ping command
shell: ping -c 1 -W 1 192.168.0.2
register: ping_cmd
changed_when: false
- name: set ping time for each host
set_fact:
ping_time: "{{ ((ping_cmd.stdout_lines[1] | split('='))[3] | split(' '))[0] }}"
- name: set total ping time once for all hosts
set_fact:
total_ping_time: "{{ play_hosts | map('extract', hostvars)
| map(attribute='ping_time') | map('float') | sum }}"
run_once: true
- name: set mean ping time once for all hosts
set_fact:
mean_ping_time: "{{ ((total_ping_time | float) / (play_hosts | length)) }}"
run_once: true
- name: show the result
debug:
msg: "For this host, ping_time is {{ ping_time }}s
for a total of {{ total_ping_time | float | round(3) }}s
and an average of {{ mean_ping_time | float | round(3) }}s"
给出:
$ ansible-playbook -i inv.yml test.yml
PLAY [all] ********************************************************************************************************************************************************************************************************
TASK [Run ping command] *******************************************************************************************************************************************************************************************
ok: [test1]
ok: [test2]
TASK [set ping time for each host] ********************************************************************************************************************************************************************************
ok: [test1]
ok: [test2]
TASK [set total ping time once for all hosts] *********************************************************************************************************************************************************************
ok: [test1]
TASK [set mean ping time once for all hosts] **********************************************************************************************************************************************************************
ok: [test1]
TASK [show the result] ********************************************************************************************************************************************************************************************
ok: [test1] => {
"msg": "For this host, ping_time is 0.137s for a total of 0.214s and an average of 0.107s"
}
ok: [test2] => {
"msg": "For this host, ping_time is 0.077s for a total of 0.214s and an average of 0.107s"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
test1 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test2 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0