选择一款配置管理软件的六大分析方向
1. 活跃度(社区)
2. 学习成本
3. 使用成本
4. 编码语言
5. 性能
6. 使用是否广泛
ansible特点
1. 模块化设计,调用特定的模块完成特定任务
2. 基于Python语言实现,支持paramiko、PyYAML (半结构化语言)、Jinja2
3. 其模块支持JSON等标准输出格式,可以采用任何编程语言重写
4. 部署简单
5. 主从模式工作
6. 支持自定义模块、支持playbook
7. 易于使用
8. 支持多层部署、支持异构IT环境
ansible优点
1. 只需要SSH和Python即可使用
2. 无客户端
3. 功能强大,模块丰富
4. 上手容易,门槛低
5. 基于Python开发,做二次开发更容易
6. 使用公司比较多,社区活跃
ansible工作流程:
先按照规则顺序读取配置信息
随之获取全部机器和分组信息列表
再按照命令参数确定执行的模块和配置
然后连接执行各个模块操作
最后把执行结果返回给管理服务器
安装ansible
两个方案,一个是RPM包安装,一个是源码安装
通过RPM包安装:
很简单,在yum源中书写一个配置文件,然后就可以用yum install -y ansible安装了
[root@ansible ~]# vim /etc/yum.repos.d/ansible.repo
[ansible]
name=Lyu_yum
baseurl=http://mirror.centos.org/centos/7/extras/x86_64/
enabled=1
gpgcheck=1
通过源码安装(可以copy直接当脚本使用):
# 对Python源码安装前的需要软件(需要extras软件扩展包,如果没有,那么需要修改yum配置文件,和RPM包安装时写的配置一样)
cat > /etc/yum.repos.d/ansible.repo <<EOF
[ansible]
name=Lyu_yum
baseurl=http://mirror.centos.org/centos/7/extras/x86_64/
enabled=1
gpgcheck=1
EOF
yum install -y epel-release
yum install -y git python2-pip python-setuptools python-devel
# 使用pip安装依赖包
pip install paramiko PyYAML Jinja2 httplib2 six
# 下载anisble源码包
git clone git://github.com/ansible/ansible.git
# 进行编译安装
python setup.py build && python setup.py install
pip install ansible
# 测试
ansible --version
安装后验证(如果能查看到版本信息等就可以通过):
ansible --version
重点知识点:
ansible配置文件查找顺序
1. 首先检测ANSIBLE_CONFIG变量定义的配置文件
2. 其次检查当前目录下的 ./ansible.cfg 文件
3. 再次检查当前用户家目录下 ~/ansible.cfg 文件
4. 最后检查/etc/ansible/ansible.cfg文件
而/etc/ansible/ansible.cfg是ansible的默认配置文件路径
修改ansible服务配置
1. 修改默认配置文件,要做的是取消下面两行开头的注释
inventory = /etc/ansible/hosts #定义托管主机地址配置文件
host_key_checking = False #关闭ssh远程的yes回答
2. 根据配置文件编写主机地址/etc/ansible/hosts
其作用是指定组的信息,以及一些主机或者组的个性化设计,下面是书写格式。
配置的基本书写格式 | [组名称] 主机名称或ip地址 参数与值 |
用范围来实现IP或者主机名的范围设定 | 在IP地址位置写192.168.1.[10:250]意思就是从192.168.1.10一直到192.168.1.250,这241个主机 |
将多个组组成一个新的组 | [组名称:children] 组名 参数与值 |
给组中的所有主机设置共性的参数信息 | [组名称:vars] 参数=具体值 |
参数(一般是用密钥,只有临时测试的时候用这些配置的密码,所以这些参数配置一般很少)
ansible_ssh_host | 将要连接的远程主机名与你想要设定的主机别名不同,可以通过此变量设置 |
ansible_ssh_port | ssh端口号:如果不是默认的端口号,通过此变量设置 |
ansible_ssh_user | 默认的ssh用户名 |
ansible_ssh_pass | ssh密码(这种方式并不安全,我们强烈建议使用--ask-pass或SSH密钥) |
ansible_sudo_pass | sudo密码(建议使用 --ask-sudo-pass) |
ansible_sudo_exe(new in version 1.8) | sudo命令路径(适用于1.8及以上版本) |
ansible_connection | 与主机的连接类型,如:local,ssh或paramiko, 1.2以前默认使用paramiko,1.2以后默认使用'smart' ,它会根据是否支持ControlPersist来判断'ssh'方式是否可行 |
ansible_ssh_private_key_file | ssh使用的私钥文件,适用于有多个密钥,而你不想使用SSH代理的情况 |
ansible_shell_type | 目标系统的shell类型,默认情况下,命令的执行使用'sh'语法,可设置为'csh'或'fish' |
ansible_python_interpreter | 目标主机的python路径,适用情况:系统中有多个Python,或者命令路径不是"/usr/bin/python" |
hosts文件范例:
[web]
192.168.1.110
192.168.1.120
[db]
192.168.1.130
192.168.1.140
[other]
192.168.1.150
[app:children]
web
db
[app:vars]
ansible_ssh_user="root"
ansible_ssh_pass="管理员密码"
ansible_ssh_port="22"
3. 测试:
ansible [组名称] --list-hosts
# 查看所有的主机信息
ansible all --list-hosts
# 检查能不能用ssh自动连接(设置好密码参数或者配置好密钥,否则失败)
ansible 主机名称或ip地址 -m ping
# 检查能不能用ssh连接,交互输入密码(不需要设置密钥,如果配置了密钥或者正确的密码参数,那么不管交互密码写的对与否都是可以监测成功的)
ansible 主机名称或ip地址 -m ping -k
注意:
1.虽然命令中写的是ping,但实质上是查看ssh能不能连接,如果目标主机的icmp协议忽略全部数据包,会发现测试依然成功ansible
[root@test ~]# sysctl -w net.ipv4.icmp_echo_ignore_all=1
[root@ansible ~]# testhost -m ping
testhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
2.在第一次连接成功后,ansible会在服务器下 ~/.ansible/cp/下创建一个文件,并保持ssh连接状态,只有过一端时间后,ansible才会断开连接,并且删除~/.ansible/cp/下相关文件,也就是说,如果我们测试的时候,发现测试成功,然后我们断开sshd服务,这时候,我们继续测试依然成功,因为连接没有断开,不过不操作一端时间后,连接就会断开
[root@ansible ~]# ansible testhost -m ping
testhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
[root@test ~]# systemctl stop sshd
[root@ansible ~]# ansible testhost -m ping
testhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
[root@ansible ~]# sleep 5m ; ansible testhost -m ping
testhost | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.1.13 port 22: Connection refused\r\n",
"unreachable": true
}
4. 不同用户,自定义自己的个性化ansible信息的解决方案
操作过程:每个用户,自己创建一个文件夹,里面写配置文件,hosts等信息(可以复制默认配置文件进行修改);
然后在这个文件夹的路径下执行ansible的命令,就是一个由自己写的配置文件自定义的ansible,而且不影响ansible的默认配置
理论原理: 其操作的原理是因为ansible的配置文件的执行顺序,相对于默认配置文件,ansible会优先读取当前所在目录下的ansible.cfg文件的内容,这样就可以实现用这个自己写的配置文件启动个性化的ansible
[root@Smart_10 ~]# mkdir /ansible/ ; cp /etc/ansible/ansible.cfg /ansible/ansible.cfg ; vim /ansible/ansible.cfg
# 自己个性化修改即可,下面是我的测试结果
[root@Smart_10 ~]# ansible all --list-hosts
hosts (1):
testhost
[root@Smart_10 ~]# cd /ansible/ ;ls
ansible.cfg hosts
[root@Smart_10 ansible]# ansible all --list-hosts
hosts (1):
192.168.1.110
JSON格式
其书写格式有3中:
1. 数组类型 (代表一个数组的值): [ "值1" , "值2" , "值n" ]
2. 键值类型 (可以理解为给一个键赋值): 键名 : 值
3. 范围类型 (让一组值成为一个对象值): {"值1" , "值2" , "值n" }
注: 这些类型中的值都可以相互嵌套替换,例如"hosts" : ["192.168.1.11", "192.168.1.12"]等
可以用python脚本生成一个JSON格式文件
#!/usr/bin/python
import json
一个对象名=对象值(可以是数组可以是对象)
print( json.dumps(一个对象名))
可以用shell脚本写(把JSON文件echo出来即可)
echo 'JSON文件的内容'
示例
python脚本:
#!/usr/bin/python
import json
hostlist = {}
hostlist["bb"] = ["192.168.1.15", "192.168.1.16"]
hostlist["aa"] = {
"hosts" : ["192.168.1.11", "192.168.1.12"],
"vars" : {
"ansible_ssh_user":"root","ansible_ssh_pass":"密码"
}
}
print( json.dumps(hostlist))
shell脚本:
echo'{
"aa" : {
"hosts" : ["192.168.1.11", "192.168.1.12"],
"vars" : {
"ansible_ssh_user" : "root",
"ansible_ssh_pass" : "密码"
}
},
"bb" : ["192.168.1.15", "192.168.1.16"],
}'
JSON文件:
{
"aa" : {
"hosts" : ["192.168.1.11", "192.168.1.12"],
"vars" : {
"ansible_ssh_user" : "root",
"ansible_ssh_pass" : "密码"
}
},
"bb" : ["192.168.1.15", "192.168.1.16"],
}
等价的Hosts文件:
[aa]
192.168.1.11
192.168.1.12
[aa::vars]
"ansible_ssh_user" : "root"
"ansible_ssh_pass" : "密码"
[bb]
192.168.1.15
192.168.1.16
ansible命令:
ansible 主机或者组名 选项
选项:
-M | 指定模块路径 |
-m | 使用模块,默认command模块 |
-a | or --args模块参数 |
-i | inventory文件路径,或可执行脚本 |
-k | 使用交互式登录密码 |
-e | 定义变量 |
-v | 详细信息, |
-vvvv | 开启debug模式 |
--list-hosts | 列出组内的主机信息 |
经典命令模板:ansible 主机或者组名 -m 模块名 -a 模块参数
模块 | 含义 | 所用参数 |
ansible-doc(很重要) | 查看帮助信息 | 这个的参数不用-a |
ping | 监测主机 | 没有参数 |
command | 批量执行命令(不写模块直接写参数的时候默认使用的就是command模块,不支持bash内部命令) | 可执行的命令 |
shell | 批量执行命令(支持bash所有的内部命令,最优) | 命令和chdir指定切换目录信息 |
raw | 批量执行命令(支持bash所有的内部命令) | 命令,没有其他参数 |
authorized_key | 部署公钥 | user用来指定远程的用户 |
exclusive指定是否覆盖已存在的公钥数据 | ||
manage_dir指定如果没有~/.ssh/是否创建 | ||
key指定自己的公钥信息 | ||
script | 将本地脚本内容传递到远程主机执行 | 脚本名 |
copy | 复制文件到远程主机 | src指定本机的文件路径和文件名或目录名 |
dest 指定远程主机的文件路径和文件名或目录名 | ||
backup 是否备份原文件,备份文件包含时间信息 | ||
force 设定是否强制强制覆盖写入该文件(具体使用看下面的注意点) | ||
lineinfile | 匹配后整行替换 | path 指定目标文件 |
regexp 指定正则表达式的匹配 | ||
line 指定整行修改成什么 | ||
replace | 匹配某个字段 | path指定目标文件 |
regexp指定正则表达式的匹配 | ||
replace指定匹配字段的值替换成什么 | ||
yum | 安装软件包 | name指定包名多个包用逗号隔开 |
state指定进行的操作(present(默认)、installed安装;absent、removed卸载) | ||
service | 控制服务的状态 | name 指定服务的名称 |
enabled 指定是否开机自启动 | ||
sleep 执行重启服务,并设定关闭后多少秒后启动 | ||
state 指定当前服务的状态(started,stopped,restarted,reloaded) | ||
setup | 查看主机信息 | filter 过滤所需要的信息 |
模块 | 示例 | 示例含义 |
ansible-doc | ansible-doc -l | 列出所有模块 |
很重要 | ansible-doc 模块名 | 查看具体的模块帮助信息 |
ping | ansible all -m ping | 批量检查主机健康性 |
command | ansible all -m command -a 'uptime' | 批量查看系统负载 |
shell | ansible all -m shell -a 'chdir=/mnt touch test' | 批量在/mnt/目录下创建一个test文件 |
raw | ansible all -m shell -a 'chdir=/mnt touch test' | chdir参数无效,所以是在~下创建一个test文件 |
authorized_key | ansible all -m authorized_key -a "user=root manage_dir=true key='$(< ~/.ssh/id_rsa.pub)'" -k -v | 给所有的机器创建公钥 exclusive=true 删除所有其他秘钥 |
script | ansible all -m script -a 'start.sh' | 批量把脚本内的内容远程到其他服务器执行 |
copy | ansible t1 -m copy -a 'src=/etc/passwd dest=/root/user.txt' | 把本机的用户信息文件拷贝到远程主机的root下命名为user.txt |
lineinfile | ansible all -m lineinfile -a 'path="/etc/selinux/config" regexp="^SELINUX=" line="SELINUX=disabled"' | 批量关闭SElinux |
replace | ansible all -m replace -a 'path="/etc/selinux/config" regexp="^(SELINUX=).*" replace="\1disabled"' | 批量关闭SElinux |
yum | ansible all -m yum -a 'name="httpd"' | 安装httpd软件包 |
service | ansible all -m service -a 'name="httpd" enabled="yes" sleep=1' | 让所有服务器的httpd网站服务关闭,1秒后启动 |
setup | ansible all -m setup -a 'filter=ansible_os_family' | 查看所有主机的系统所属系列信息 |
注意点:
1. 模块commond不能执行bash相关的内部命令,包括下面的命令不能执行
1.1 若命令里有如下字符则执行不成功 "<" , ">" , "|" , "&"
1.2 不启动shell直接在ssh进程中执行,所有使用到shell的命令执行都会失败,例如set命令等等
2. 对比commond、shell、raw三个模块:
2.1 模块commond是默认模块,综合使用性能一般,不支持bash的内置命令
2.2 模块shell是最优模块,性能最好,支持所有内容,支持所有,不过可能
2.3 模块raw是泛用行最广的,支持bash的基本功能,但没有参数
总结下来,最优先考虑shell,不能用再考虑raw,不写的时候默认是commond
3. 使用模块copy,参数src使用时,如果目录以/结尾那么只复制目录内的文件,如果目录不以/结尾那么复制整个目录
参数dest使用时,如果源文件是目录,那么路径也必须是目录
参数src和dest后面的文件名或者目录名不一定要一模一样
参数force使用时,如果值为yes,那么会强制覆盖远程主机的原文件,如果值为no,那么只有当远程主机不存在的时候才复制
4. 执行ansible命令的时候,不要随便ctrl+c终止,可能会导致远程主机的系统出现问题
ansible的七个操作
1. ansible: 用于执行临时性的工作
2. ansible-doc: ansible模块的文档说明
3. ansible-console: ansible为用户提供的交互式工具
4. ansible-galaxy: 从github上下载管理Roles的一款工具
5. ansible-playbook: 日常应用中使用频率最高的命令
6. ansible-vault: 主要用于配置文件加密
7. ansible-pull: 适用于配置大批量机器的场景下,效率几乎可以无限提升,但对运维人员的技术水平和前瞻性规划有较高要求
ansible -- playbook
playbook语法格式
因为playbook死由YAML语言编写,所以语法格式遵循YAML标准
playbook由一个或多个play组成,每个play中 hosts,variables,roles,tasks 等对象的表示方法都是键值中间以": "分隔表示
注意YAML格式的文件开始行都应该是 --- ,这是YAML格式的一部分,表明一个文件的开始
在使用的时候我们可以通过 ansible-doc 模块 来查看帮助信息,里面的EXAMPLES会有例子作为参考
playbook构成
hosts | 内容是一个(多个)组或主机的patterns,以逗号为分隔符,如果使用all代表指代所有主机 |
remote_user | 指定登陆使用的账户 |
target | 定义将要执行playbook的远程主机组 |
variable | 定义playbook运行时需要使用的变量 |
tasks | 定义将要在远程主机上执行的任务列表 |
Handler | 定义task执行完成以后需要调用的任务 |
对于tasks模块注意点
1. 每一个play包含了一个task列表(任务列表)
2. 一个task在其所对应的所有主机上(通过 host pattern匹配的所有主机)执行完毕之后,下一个task才会执行
3. 在一个play之中,所有hosts会获取相同的任务指令,这是play的一个目的所在,即将一组选出的hosts映射到task,执行相同的操作
使用命令运行playbook文件:
ansible-playbook yaml文件 [-f 并发进程个数上限]
示例:
# 测试所有的机器是否健康
vim ping.yml
---
- hosts: all
remote_user: root
tasks:
- ping:
# 给web组的服务器安装配置httpd服务器,并修改其监听端口,开启服务器和设置开机自启动
vim ping.yml
---
- hosts: web
remote_user: root
tasks:
- name: install the latest version of Apache
yum:
name: httpd
state: present
- lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen'
line: 'Listen 8080'
- replace:
path: /etc/httpd/conf/httpd.conf
regexp: '#(ServerName).*'
replace: '\1 www.lyu.com'
- name: write http host file
shell: echo 'hello world' > /var/www/html/index.html
- service:
name: httpd
state: started
- service:
name: httpd
enabled: yes
语法进阶
1. 使用变量参数
1.1 用法格式: 用vars代表变量定义,用{{变量名}}调用
例如:
---
- hosts: all
remote_user: root
vars:
service: maraidb
tasks:
- name: install "{{service}}"
yum:
name: {{service}}
state: present
- service:
name: {{service}}
state: started
1.2 给简单变量通过命令参数进行赋值,例如上面这个yaml文件,为执行的时候想service变量变成httpd
ansible-playbook install.yml -e service="httpd"
ansible-playbook yml文件名 -e 参数名="设置的参数值"
1.3 定义复杂变量,格式如下
---
- hosts: all
remote_user: root
vars:
service:
name: "maraidb"
free: "免费开源"
tasks:
- name: install "{{service.name}}" "{{service.free}}"
yum:
name: {{service.name}}
state: present
- service:
name: {{service.name}}
state: started
使用的时候调用:
{{service.name}} 代表 maraidb
{{service.free}} 代表 免费开源
1.4 给复杂变量进行传参 (有两个方案)
1.4.1 使用JSON格式上传参数数据
ansible-playbook install.yml -e "{"service":{"name":"oracle","free":"收费闭源"}}"
ansible-playbook yml文件名 -e "{"参数":{"参数字段1":"值","参数字段2":"值"}}"
1.4.2 使用一个yml格式的文件进行传参
# 写一个yml文件(vars.yml),然后以这个文件为参数传递到playbook中
service:
name: "oracle"
free: "收费闭源"
ansible-playbook install.yml -e "@vars.yml(@刚刚取的文件名)"
1.5 用于解决密码明文的问题:
问题源: user模块的password常常设置密码失败,其原因是因为password是把字符串直接写入shadow,并没有改变,而Linux的shadow密码是经过加密的,所以不能使用。
解决反感:通过管道进行过滤,这样下面的变量值就可以和user模块的password结合实现设置密码
{{ '密码明文' | password_hash('sha512')}}
例如:创建一个testuser用户,密码为123456,并要求其第一次登陆时修改密码
---
- hosts: all
remote_user: root
vars:
username: testuser
tasks:
- name: create user "{{username}}"
user: password={{'123456' |password_hash('sha512')}} name={{username}}
- shell: chage -d 0 {{username}}
2. 错误处理 error
默认当ansible程序运行中,当某个命令执行后,$?返回值不是0,那么ansible会停止命令并返回error
可是有的时候,我们需要忽略错误继续运行,忽略错误有两个操作
一个方法是让命令后无论对错 $?都为0;这样ansible执行中不管是否有问题都不会报错
shell: 执行的命令命令 || /bin/true
另一个方法是通过参数设置,让ansible忽略error;会显示报错,而且只对所跟的这个shell生效 (推荐使用)
shell: 执行的命令命令
ignore_errors: True
3. 逻辑处理 handlers(和task平级)
避免有多次改变发生时每次都执行指定的操作,取而代之仅在所有的变化发生完成后一次性地执行指定操作
可以理解为C、Java的函数,数据库中的存储对象,它是简化逻辑思路,只要要调用的时候写就好,不管写了多少个,再最后都将执行一次。
但是它不是当读取的时候立刻执行,他是读取后,记录这个命令要执行,当tasks完整执行后再执行handlers的命令。
注意:
1. 使用notify调用的是handler段的name定义的串,必须一致,否则达不到触发的效果
2. 多个task触发同一个notify的时候,同一个服务只会触发一次
3. 而且notify可以触发多个条件,在生产环境中往往涉及到某一个配置文件的改变要重启若干服务的场景,handler用到这里非常适合
4. 结合vars可以写出非常普适的服务管理脚本。
---
- hosts: all
remote_user: root
tasks:
- name: config httpd.conf
copy:
src=/root/playbook/httpd.conf
dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: write http host file
shell: echo 'hello world' > /var/www/html/index.html
handlers:
- name: restart httpd
service:
name=httpd
state=restarted
4. 判断处理 when
而when判断只对当前的所在的块有效
---
- name: Install httpd
hosts: all
tasks:
- name: Install httpd via yum
yum: name=httpd state=installed
when: ansible_os_family == "RedHat"
- name: Install VIM via apt
apt: name=httpd state=installed
when: ansible_os_family == "Debian"
5. 获取保存值 register
有时候我们还需要更复杂的例子,如判断前一个命令的执行结果去处理后面的操作,这时候就需要register模块来保存前一个命令的返回状态,在后面进行调用。
可以和判断结合起来,把上一个命令的结果存在一个值中,然后进行when判断。
# 举例:对系统负载进行监测以及特殊处理,出现问题的话就报错
---
- hosts: all
remote_user: root
tasks:
- shell: uptime |awk '{printf("%f\n",$(NF-2))}'
register: result
- shell: echo 'error, free is not enough' | mail -s 'Error' -u xxx@yy.com
when: result.stdout|float > 0.5
- service:
name=httpd
state=stopped
when: result.stdout|float > 0.8
# 其中 result.stdout|float 代表把数据改成数字
6. 循环语句with_items
可以理解为Linux的for循环,只不过是写在后面,而循环中的值由变量item代替。
---
- hosts: all
remote_user: root
tasks:
- name: add users
user:
name={{item.name}}
group={{item.group}}
password={{'123456' |password_hash('sha512')}}
with_items:
- {name: "test1", group: "root"}
- {name: "test2", group: "root"}
- {name: "test3", group: "bash"}
- {name: "test4", group: "bash"}
6. 嵌套循环 with_nested
---
- hosts: all
remote_user: root
vars:
un: [a, b, c]
id: [1, 2, 3]
tasks:
- name: add users
shell: echo {{item}}
with_nested:
- "{{un}}"
- "{{id}}"
组合与标记
1. 标记 tags
给指定的任务定义一个调用标识,而客户可以在操作端直接调用,使用 ansible-playbook yml文件内容 --tags=标记名
---
- hosts: all
remote_user: root
vars:
soft: httpd
tasks:
- name: install {{soft}}
yum: name={{soft}}
- name: config httpd.conf
copy:
src=/root/playbook/httpd.conf
dest=/etc/httpd/conf/httpd.conf
- name: config services
copy:
src=/root/playbook/httpd.conf
dest=/etc/httpd/conf/httpd.conf
- name: restart services
service:
name={{soft}}
enabled=yes
state=restarted
tags: restartweb
# 执行的时候,只执行标记的那个块的内容
ansible-playbook yml文件内容 --tags=restartweb
2. 获取其他yml文件中的内容 include and roles
在编写 playbook 的时候随着项目越来越大,playbook越来越复杂,修改也很麻烦。
这时可以把一些play、task 或handler放到其他文件中,通过include指令包含进来是一个不错的选择
执行roles像是加强版的include,它可以引入一个项目的文件和目录
一般所需的目录层级有
vars | 变量层 |
tasks | 任务层 |
handlers | 触发条件 |
files | 文件 |
template | 模板 |
default | 默认,优先级最低 |
调试
只是测试运行,不真实运行 | ansible-playbook -C --list-tasks --list-hosts |
显示受到影响的主机host | --list-hosts |
显示工作的task | --list-tasks |
显示将要运行的tag | --list-tags |
---
- hosts: all
remote_user: root
tasks:
- shell: uptime |awk '{printf("%f\n",$(NF-2))}'
register: result
- shell: touch /tmp/isreboot
when: result.stdout|float > 0.5
- name: Show debug info
debug: var=result