Linux大型架构——ansible服务器的搭建和基本使用

选择一款配置管理软件的六大分析方向
   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 exclusive=true manage_dir=true key='$(< ~/.ssh/id_rsa.pub)'" -k -v 给所有的机器创建公钥
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 [email protected]
      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

猜你喜欢

转载自blog.csdn.net/Yu1543376365/article/details/84329687