来自 电脑知识 2019-09-19 04:31 的文章
当前位置: 威尼斯国际官方网站 > 电脑知识 > 正文

【威尼斯国际官方网站】playbook模式及语法,pl

一、什么是playbook及其组成

Ansible系列(五):playbook应用和roles自动化批量安装示例,ansibleplaybook

本文目录:
1.1 yaml语法和示例
1.2 ansible-playbook命令说明及playbook书写简单示例
1.3 playbook基础
  1.3.1 hosts和remote_user
  1.3.2 task list
  1.3.3 notify和handler
  1.3.4 标签tags
1.4 include和roles
  1.4.1 include
  1.4.2 roles
1.5 roles示例:批量自动化安装

playbook是ansible实现批量自动化最重要的手段。在其中可以使用变量、引用、循环等功能,相比ad-hoc而言,其功能要强大的多。

什么是playbook

playbook 翻译过来就是"剧本"

1.1 yaml简单示例

ansible的playbook采用yaml语法。以下是一个yaml格式的文件:

---
# Members in Bob's family
    name: Bob
    age: 30
    gender: Male
    wife: 
        name: Alice
        age: 27
        gender: Female
    children: 
      - name: Jim
        age: 6
        gender: Male
      - name: Lucy
        age: 3
        gender: Female

playbook的组成

play:定义的是主机的角色
task:定义的是具体执行的任务
playbook:由一个或多个play组成,一个play可以包含多个task

威尼斯国际官方网站 1

 

1.2 ansible-playbook命令说明及playbook书写简单示例

以下是一个简单的playbook示例。该示例执行两个任务,第一个任务是执行一个/bin/date命令,第二个任务是复制/etc/fstab文件到目标主机上的/tmp下,它们分别使用了ansible的command模块和copy模块。

cat /tmp/test.yaml 
---
    - hosts: centos7
      tasks: 
        - name: execute date cmd
          command: /bin/date
        - name: copy fstab to /tmp
          copy: src=/etc/fstab dest=/tmp

书写好playbook后,使用ansible-playbook命令来执行。ansible-playbook命令的选项和ansible命令选项绝大部分都相同。但也有其特有的选项。以下是截取出来的帮助信息。

ansible-playbook --help
Usage: ansible-playbook playbook.yml

Options:
  -e EXTRA_VARS,--extra-vars=EXTRA_VARS # 设置额外的变量,格式为key/value。-e "key=KEY",
                                        # 如果是文件方式传入变量,则-e "@param_file"
  --flush-cache          # 清空收集到的fact信息缓存
  --force-handlers       # 即使task执行失败,也强制执行handlers
  --list-tags            # 列出所有可获取到的tags
  --list-tasks           # 列出所有将要被执行的tasks
  -t TAGS,--tags=TAGS    # 以tag的方式显式匹配要执行哪些tag中的任务
  --skip-tags=SKIP_TAGS  # 以tag的方式忽略某些要执行的任务。被此处匹配的tag中的任务都不会执行
  --start-at-task=START_AT_TASK # 从此task开始执行playbook
  --step                 # one-step-at-a-time:在每一个任务执行前都进行交互式确认
  --syntax-check         # 检查playbook语法

现在执行上面的test.yaml。

ansible-playbook /tmp/test.yaml 

PLAY [centos7] **********************************************************************

TASK [Gathering Facts] **************************************************************
ok: [192.168.100.64]
ok: [192.168.100.65]
ok: [192.168.100.63]

TASK [execute date cmd] *************************************************************
changed: [192.168.100.63]
changed: [192.168.100.64]
changed: [192.168.100.65]

TASK [copy fstab to /tmp] ***********************************************************
changed: [192.168.100.64]
changed: [192.168.100.63]
changed: [192.168.100.65]

PLAY RECAP **************************************************************************
192.168.100.63             : ok=3    changed=2    unreachable=0    failed=0
192.168.100.64             : ok=3    changed=2    unreachable=0    failed=0
192.168.100.65             : ok=3    changed=2    unreachable=0    failed=0

从以上结果中,可以看出:(1)默认情况下,ansible-playbook和ansible是一样的,都是同步阻塞模式,需要先在所有主机上执行完一个任务,才会继续下一个任务;(2)在执行前会自动收集fact信息;(3)从显示结果中可以判断出任务是否真的执行了,抑或者是因为幂等性而没有执行。(4)每一个play都包含数个task,且都有响应信息play recap。

二、playbook的优势

1、功能比adhoc更全
2、控制好依赖
3、展现更直观
4、持久使用

1.3 playbook的内容

三、playbook的配置语法

1.3.1 hosts和remoter_user

对于playbook中的每一个play,使用hosts选项可以定义要执行这些任务的主机或主机组,还可以使用remote_user指定在远程主机上执行任务的用户,实际上remote_user是ssh连接到被控主机上的用户,自然而然执行命令的身份也将是此用户。

例如:

---
    - hosts: centos6,centos7,192.168.100.59
      remote_user: root
      tasks: XXXXXX

还可以在某个task上单独定义执行该task的身份,这将覆盖全局的定义。

---
    - hosts: centos6,centos7,192.168.100.59
      remote_user: root
      tasks: 
        - name: run a command
          shell: /bin/date
        - name: copy a file to /tmp
          copy: src=/etc/fstab dest=/tmp
          remote_user: myuser

也支持权限升级的方式。

---
    - hosts: centos6,centos7,192.168.100.59
      remote_user: yourname
      tasks: 
        - name: run a command
          shell: /bin/date
        - name: copy a file to /tmp
          copy: src=/etc/fstab dest=/tmp
          become: yes
          become_method: sudo
          become_user: root    # 此项默认值就是为root,所以可省

从上面的示例可以看出remote_user实际上并不是执行任务的绝对身份,它只是ssh连接过去的身份,只不过没有指定become的时候,它正好就用此身份来运行任务。

基本使用

1.3.2 task list

1.特性
每个play都包含一个hosts和一个tasks,hosts定义的是inventory中待控制的主机,tasks下定义的是一系列task任务列表,比如调用各个模块。这些task按顺序一次执行一个,直到所有被筛选出来的主机都执行了这个task之后才会移动到下一个task上进行同样的操作。

需要注意的是,虽然只有被筛选出来的主机会执行对应的task,但是所有主机(此处的所有主机表示的是,hosts选项所指定的那些主机)都会收到相同的task指令,所有主机收到指令后,ansible主控端会筛选某些主机,并通过ssh在远程执行任务。也就是说,如果查看ansible-playbook -vvvv的信息,将会发现临时任务文件会通过sftp发送到所有的被控主机上,但是只有一部分被筛选(如果进行了筛选)的主机才会ssh过去并远程执行命令。

当某一台被控主机执行某个任务出错或失败时,它将会被移除出任务轮询列表。也就是说,对于某主机来说,某任务执行失败,后续的所有任务都不会再去执行。当然,这不会影响其他的主机执行任务(除非主机的任务之间有依赖关系)。

最重要的是,ansible中的task是幂等性的,多次执行不会影响那些成功执行过的任务。另外幂等性还表现在执行失败后如果修正了playbook再次执行,将不会影响那些原本已经执行成功的任务,即使是不同主机也不会影响。仅这方面而言,ansible对于排错来说是极其友好的。当然,某些特殊的模块或者特殊定义的task并不一定总是幂等的,例如最简单的,执行一个command或者shell模块的命令,它会重复执行。但也有办法使其变得幂等,以command和shell模块为例,它们有两个选项:creates和removes,它们分别表示被控主机上指定的文件存在(不存在)时就不执行命令。

2.定义task的细节

  • (1).可以为每个task加上name项,也可以多个task依赖于一个name。

例如下面的两个例子。从两个示例中可以看出,两个task其实都是属于一个name的,第二个task无需再使用name命名。

示例一:

tasks: 
    - name: do something to initialize mariadb
      file: path=/mydata/data state=directory owner=mysql group=mysql mode=0755
    - shell: /usr/bin/mysql_install_db --datadir=/mydata/data --user=mysql creates=/mydata/data/ibdata1

示例二:

tasks: 
    - name: echo var passed by nginx 
      shell: echo "{{ hi_var }}"
      register: var_result
    - debug: msg="{{ var_result.stdout }}"

实际上,name只是一种描述性语句,它可以定义在任何地方。例如,定义在play的顶端。

---
- name: start a play
  hosts: localhost
  tasks:
  • (2).既然是task,那么必然会有其要执行的一个或多个任务,其本质是加载并执行ansible对应的模块。在playbook中,每调用的一个模块都称为一个action。

例如,定义一个确保服务是启动状态的task,有以下三种方法传递模块参数:

tasks: 
  - name: be sure the sshd is running
    service: name=sshd state=started     # 方法一: 定义为key=value,直接传递参数给模块

    service:                             # 方法二: 定义为key: value方式
      name: sshd
      state: started

    service:                  # 方法三: 使用args内置关键字,然后定义为key: value方式
    args: 
      name: sshd
      state: started

但要注意,ping模块、command和shell模块是不需要key=value格式的。对于ping命令,可以直接省略key=value。对于command和shell,只需要给定命令路径和要接上去的选项或参数即可,且无法使用上面的方法二。例如下面定义的是一个ntpdate命令,只需给定它的参数即可。

tasks: 
    - name: execute command ntpdate
      shell: /usr/sbin/ntpdate ntp1.aliyun.com
    - name: ping host
      ping:

对于command或shell模块来说,有时候要考虑命令的返回状态码。如果要忽略非0状态码继续执行任务,可以使用以下两种方式:

tasks: 
    - name: ignore non_zero return code
      shell: /usr/sbin/ntpdate ntp1.aliyun.com || /bin/true

或者

tasks: 
    - name: another way to ignore the non_zero return code
      shell: /usr/sbin/ntpdate ntp1.aliyun.com
      ignore_errors: true
  • (3).如果action的key=value太多,导致内容太长,可以在上一行的缩进级别基础上继续缩进表示续行。

例如,下面的owner比src多缩进了4个空格。

tasks:
  - name: Copy ansible inventory file to client
    copy: src=/etc/fstab dest=/tmp
              owner=root group=root mode=0644
  • (4).在action的value部分,可以引用已经定义的变量,可以是已定义好的自定义的变量,也可以是内置变量。变量相关内容见后文。

  • (5).使用include指令,可以将其他的playbook文件包含到此playbook文件中。include的方式见下文。

playbook基础使用

ansible-playbook playbook.yml [options]

-u REMOTE_USER, --user=REMOTE_USER 
# ssh 连接的用户名 
-k, --ask-pass 
#ssh登录认证密码 
-s, --sudo 
#sudo 到root用户,相当于Linux系统下的sudo命令
-U SUDO_USER, --sudo-user=SUDO_USER 
#sudo 到对应的用户 
-K, --ask-sudo-pass #用户的密码(—sudo时使用) 
-T TIMEOUT, --timeout=TIMEOUT 
# ssh 连接超时,默认 10 秒 
-C, --check # 指定该参数后,执行 playbook 文件不会真正去执行,而是模拟执行一遍,然后输出本次执行会对远程主机造成的修改 
-e EXTRA_VARS, --extra-vars=EXTRA_VARS 
# 设置额外的变量如:key=value 形式 或者 YAML or JSON,以空格分隔变量,或用多个-e 
-f FORKS, --forks=FORKS # 进程并发处理,默认 5 
-i INVENTORY, --inventory-file=INVENTORY 
# 指定 hosts 文件路径,默认 default=/etc/ansible/hosts 
-l SUBSET, --limit=SUBSET 
# 指定一个 pattern,对- hosts:匹配到的主机再过滤一次 
--list-hosts # 只打印有哪些主机会执行这个 playbook 文件,不是实际执行该 playbook 
--list-tasks # 列出该 playbook 中会被执行的 task 
--private-key=PRIVATE_KEY_FILE # 私钥路径 
--step # 同一时间只执行一个 task,每个 task 执行前都会提示确认一遍 
--syntax-check # 只检测 playbook 文件语法是否有问题,不会执行该 playbook 
-t TAGS, --tags=TAGS #当 play 和 task 的 tag 为该参数指定的值时才执行,多个 tag 以逗号分隔 
--skip-tags=SKIP_TAGS # 当 play 和 task 的 tag 不匹配该参数指定的值时,才执行 
-v, --verbose #输出更详细的执行过程信息,-vvv可得到所有执行过程信息。

原文链接:https://www.imooc.com/article/22729

1.3.3 notify和handler

ansible中几乎所有的模块都具有幂等性,这意味着被控主机的状态是否发生改变是能被捕捉的,即每个任务的changed=true或changed=false。ansible在捕捉到changed=true时,可以触发notify组件(如果定义了该组件)。

notify是一个组件,并非一个模块,它可以直接定义action,其主要目的是调用handler。例如:

tasks: 
    - name: copy template file to remote host
      template: src=/etc/ansible/nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: 
        - restart nginx
        - test web page
      copy: src=nginx/index.html.j2 dest=/usr/share/nginx/html/index.html
      notify: 
        - restart nginx

这表示当执行template模块的任务时,如果捕捉到changed=true,那么就会触发notify,如果分发的index.html改变了,那么也重启nginx(当然这是没必要的)。notify下定义了两个待调用的handler。handler主要用于重启服务或者触发系统重启,除此之外很少使用handler。以下是这两个handler的内容:

handlers: 
    - name: restart nginx
      service: name=nginx state=restarted
    - name: test web page
      shell: curl -I http://192.168.100.10/index.html | grep 200 || /bin/false

handler的定义和tasks的定义完全一样,唯一需要限定的是handler中task的name必须和notify中定义的名称相同。

注意,notify是在执行完一个play中所有task后被触发的,在一个play中也只会被触发一次。意味着如果一个play中有多个task出现了changed=true,它也只会触发一次。例如上面的示例中,向nginx复制配置文件和复制index.html时如果都发生了改变,都会触发重启apache操作。但是只会在执行完play后重启一次,以避免多余的重启。

使用场景

1.3.4 标签tag

可以为playbook中的每个任务都打上标签,标签的主要作用是可以在ansible-playbook中设置只执行哪些被打上tag的任务或忽略被打上tag的任务。

tasks: 
   - name: make sure apache is running
     service: name=httpd state=started
     tags: apache
   - name: make sure mysql is running
     service: name=mysqld state=started
     tags: mysql

以下是ansible-playbook命令关于tag的选项。

  --list-tags           # list all available tags
  -t TAGS, --tags=TAGS  # only run plays and tasks tagged with these values
  --skip-tags=SKIP_TAGS # only run plays and tasks whose tags do not match these values

1、playbook的配置

示例:

---
- hosts : 192.168.56.11
  remote_user : root
  vars :
          touch_file : devops.file
  tasks :
          - name : touch file
            shell: "touch /tmp/{{touch_file}}"

 

 

1.4 include和roles

如果将所有的play都写在一个playbook中,很容易导致这个playbook文件变得臃肿庞大,且不易读。因此,可以将多个不同任务分别写在不同的playbook中,然后使用include将其包含进去即可。而role则是整合playbook的方式。无论是include还是role,其目的都是分割大playbook以及复用某些细化的play甚至是task。

2、执行

devops@devops-virtual-machine:/etc/ansible$ cat /etc/ansible/hosts
[test_group1]
#192.168.56.11:22 ansible_ssh_user=root ansible_ssh_pass='1234567'
#192.168.56.11:22 ansible_ssh_user=root ansible_ssh_key_file=/home/devops/.ssh/id_rsa
192.168.56.11:22 ansible_ssh_user=root

#列出f1.yml指的的主机与/etc/ansible/hosts匹配到的主机
devops@devops-virtual-machine:/etc/ansible$ ansible-playbook -i /etc/ansible/hosts --list-hosts ./f1.yml

playbook: ./f1.yml

  play #1 (192.168.56.11): 192.168.56.11    TAGS: []
    pattern: ['192.168.56.11']
    hosts (1):
      192.168.56.11




devops@devops-virtual-machine:/etc/ansible$ ansible-playbook -i /etc/ansible/hosts ./f1.yml

PLAY [192.168.56.11] ***********************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.56.11]

TASK [touch file] **************************************************************************************************************
 [WARNING]: Consider using file module with state=touch rather than running touch

changed: [192.168.56.11]

PLAY RECAP *********************************************************************************************************************
192.168.56.11              : ok=2    changed=1    unreachable=0    failed=0

 

3、执行结果返回

  • 红色:表示有task执行失败或者提醒的信息
  • 黄色:表示执行了且改变了远程主机状态
  • 绿色:表示执行成功

1.4.1 include

可以将task列表和handlers独立写在其他的文件中,然后在某个playbook文件中使用include来包含它们。除此之外,还可以写独立的playbook文件,使用include来包含这个文件。

也即是说,include可以导入两种文件:导入task、导入playbook。

1.一种是任务列表式的文件(没有tasks或handlers指令),它只能在tasks或handlers指令的子选项处使用include包含。这种方式可以传递变量到被包含的文件中。

假设某个task列表文件/yaml/a.yaml内容如下:

---
    - name: execute ntpdate
      shell: /usr/sbin/ntpdate ntp1.aliyun.com

在同目录/yaml下有一个名为test.yaml的playbook(除了role,playbook中所有相对路径都是基于playbook或inventory的),在此playbook中使用include来包含它,如果使用相对路径将会包含同目录下的文件。

---
    - hosts: centos7
      tasks:
       - include: a.yaml

可以在include的时候传递变量给对应的文件,这样在被包含的文件中就可以引用该变量的值。

---
  - hosts: centos7
    tasks:
      - include: a.yaml sayhi="hello world"

或者

---
  - hosts: centos7
    tasks:
       - include: a.yaml
         vars: 
           sayhi: "hello world"

然后可以在被包含的文件a.yaml中使用该变量。例如:

---
    - name: execute ntpdate
      shell: /usr/sbin/ntpdate ntp1.aliyun.com
    - name: say hi to world
      debug: msg="{{ sayhi }}"

执行该test.yaml,将会输出对应的变量值。

ansible-playbook /yaml/test.yaml

PLAY [centos7] **************************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [192.168.100.64]
ok: [192.168.100.63]
ok: [192.168.100.65]

TASK [execute ntpdate] *******************************************************************
changed: [192.168.100.64]
changed: [192.168.100.65]
changed: [192.168.100.63]

TASK [sayhi to world] *******************************************************************
ok: [192.168.100.63] => {
    "changed": false, 
    "msg": "hello world"
}
ok: [192.168.100.65] => {
    "changed": false, 
    "msg": "hello world"
}
ok: [192.168.100.64] => {
    "changed": false, 
    "msg": "hello world"
}

PLAY RECAP ******************************************************************************
192.168.100.63             : ok=3    changed=1    unreachable=0    failed=0   
192.168.100.64             : ok=3    changed=1    unreachable=0    failed=0   
192.168.100.65             : ok=3    changed=1    unreachable=0    failed=0

2.另一种是include整个playbook文件,即include的动作是加载一个或多个play,所以写在顶级列表的层次。

- name: this is a play at the top level of a file
  hosts: all
  remote_user: root

  tasks:

  - name: say hi
    tags: foo
    shell: echo "hi..."

- include: load_balancers.yml  sayhi="hello world"
- include: webservers.yml
- include: dbservers.yml

    any other operations

需要说明的是,在ansible 2.4版本中,添加了includes和imports两种导入的方式,它们对静态和动态导入支持的更细化,而ansible 2.3及以前的include语句已经废弃,但仍可用。相关官方手册地址。

主机匹配

 

 

 

1.4.2 roles

roles意为角色,主要用于封装playbook实现复用性。在ansible中,roles通过文件的组织结构来展现。

对于一个role,它的文件组织结构如下图所示。

              威尼斯国际官方网站 2

首先需要有一个roles目录。同时,在roles目录所在目录中,还要有一个playbook文件,此处为nginx.yml,nginx.yml文件是ansible-playbook需要执行的文件,在此文件中定义了角色,当执行到角色时,将会到roles中对应的角色目录中寻找相关文件。

roles目录中的子目录是即是各个role。例如,此处只有一个名为nginx的role,在role目录中,有几个固定名称的目录(如果没有则忽略)。在这些目录中,还要有一些固定名称的文件,除了固定名称的文件,其他的文件可以随意命名。以下是各个目录的含义:

  • tasks目录:存放task列表。若role要生效,此目录必须要有一个主task文件main.yml,在main.yml中可以使用include包含同目录(即tasks)中的其他文件。
  • handlers目录:存放handlers的目录,若要生效,则文件必须名为main.yml文件。
  • files目录:在task中执行copy或script模块时,如果使用的是相对路径,则会到此目录中寻找对应的文件。
  • templates目录:在task中执行template模块时,如果使用的是相对路径,则会到此目录中寻找对应的模块文件。
  • vars目录:定义专属于该role的变量,如果要有var文件,则必须为main.yml文件。
  • defaults目录:定义角色默认变量,角色默认变量的优先级最低,会被任意其他层次的同名变量覆盖。如果要有var文件,则必须为main.yml文件。
  • meta目录:用于定义角色依赖,如果要有角色依赖关系,则文件必须为main.yml。

所以,相对完整的role的文件组织结构如下图。

              威尼斯国际官方网站 3

如果是多个role,则在roles同级目录下定义多个入站(作用类似于C语言的main函数)文件(如上面的nginx.yml),并在roles目录下创建对应的role目录即可。

              威尼斯国际官方网站 4

当然,如果不是使用相对路径,那么role的文件结构就无所谓了,但是roles功能开发出来,就是为了解决文件混乱和playbook臃肿问题的。所以如果可以,尽量使用推荐的role文件结构。

另外,如果role中出现的task、var、handler等和单独定义的对象同名冲突了,则优先执行role中的内容。

以下是nginx role的入站文件nginx.yml的内容。

---
  - hosts: centos7
    roles:
      - nginx

更多更详细的role用法以及组织结构,见下面的示例。

yaml语法和变量

1.5 roles示例:批量自动化安装

下面演示的是使用role批量自动安装nginx和mysql(CentOS 6)或maridb(CentOS 7)的示例。由于被控节点有CentOS 6和CentOS 7两种发行版的操作系统,因此除了要挑选对应的数据库,还要让nginx的配置文件适应各操作系统,因为nginx在这两个版本的系统上配置内容有所不同。在此,nginx、mysql和mariadb是3个role,且让nginx role依赖于mysql或mariadb role。

下面的例子中,有些地方是不太合理或多余的行为,但是作为学习示例,可以很好的理解roles之间的组织结构和相关的操作。

首先是文件的结构。

威尼斯国际官方网站 5

威尼斯国际官方网站 6

其中site.yml是入站文件,用于调用nginx、mysql和mariadb这3个role,这个文件中的内容如下。它有3个作用:(1)在调用roles之前,先根据发行版配置好yum源(pre_tasks);(2)调用nginx role,此处没有调用mysql和mariadb这两个role,因为在nginx role的meta/main.yml文件中定义了nginx role依赖于这两个role,所以此处可以不用定义;(3)在执行完nginx role之后,输出一个提示信息(post_tasks)。

cat /yaml/site.yml
---
  - hosts: centos
    remote_user: root

 # 根据发行版配置好yum源,使用when进行条件判断   
    pre_tasks: 
        - name: config the yum repo for centos 7
          yum_repository:
              name: epel
              description: epel
              baseurl: http://mirrors.aliyun.com/epel/7/$basearch/
              gpgcheck: no
          when: ansible_distribution_major_version == "7"

        - name: config the yum repo for centos 6
          yum_repository:
              name: epel
              description: epel
              baseurl: http://mirrors.aliyun.com/epel/6/$basearch/
              gpgcheck: no
          when: ansible_distribution_major_version == "6"

    roles: 
        - nginx

# 输出over消息
    post_tasks:
      - shell: echo 'deploy nginx/mysql over'
        register: ok_var
      - debug: msg='{{ ok_var.stdout }}'

以下是nginx role中的各文件内容。其中template复制的源文件都是从centos 6 nginx和centos 7 nginx上提取的,只不过是重新命名了而已。

/yaml/roles/nginx/tasks/main.yml 
---
   - name: make sure nginx state is installed
     yum: name=nginx state=installed

   - name: template nginx.conf
# 基于变量赋值配置文件模板,检查配置文件语法,并在必要的时候触发handler
     template: src=nginx{{ ansible_distribution_major_version }}.conf.j2
                  dest=/etc/nginx/nginx.conf
                  validate="/usr/sbin/nginx -t -c %s"  
     notify: 
        - restart nginx

# 基于jinja2渲染模板文件,且改变时也触发重启操作
   - name: copy index.html
     template: src=index.html.j2 dest=/usr/share/nginx/html/index.html
     notify: 
        - restart nginx

   - name: make sure nginx service is running
     service: name=nginx state=started

# 引用变量 nginx_port,在vars/main.yml中定义了
   - name: make sure port is open
     wait_for: port="{{ nginx_port }}"

/yaml/roles/nginx/handlers/main.yml 
---
   - name: restart nginx
     service: name=nginx state=restarted

/yaml/roles/nginx/vars/main.yml 
nginx_port: 80

# 定义nginx依赖于MySQL或mariadb,具体依赖于哪个,是通过条件进行判断的,centos 6表示依赖于mysql,centos 7表示依赖于mariadb
# 同时传递了两个值给变量hi_var,由于是在依赖的时候传递的,所以这两个变量可直接在依赖的role(mysql role或mariadb role)的playbook中引用
/yaml/roles/nginx/meta/main.yml 
---
   dependencies: 
     - { role: mysql,hi_var: "hello mysql",when: "ansible_distribution_major_version == '6'" }
     - { role: mariadb,hi_var: "hello mariadb",when: "ansible_distribution_major_version == '7'" }

上面拷贝了index.html.j2,其内容为:

shell> cat /yaml/roles/nginx/templates/index.html.j2 
<h1>hello from {{ ansible_default_ipv4.address }}<h1>

在template执行时,它会使用jinja2引擎对文件中的变量进行替换,使得在拷贝到不同主机时,该index.html的内容是基于远程主机ip的。此处使用的变量是收集到的facts中的变量"ansible_default_ipv4.address"。

以下是mysql role中各文件的内容。注意,MySQL的my.cnf和mariadb的my.cnf默认情况下并不一样(mariadb的my.cnf默认多了一项配置"!includedir /etc/my.cnf.d",MySQL需要取消该项),所以需要分别提供。

/yaml/roles/mysql/tasks/main.yml 
---
    - name: make sure mysql is installed
      yum: name=mysql-server state=installed

# 特别需要注意下面的初始化命令,由于执行的是shell模块,所以要考虑其幂等性,显然初始化动作是一定要实现幂等性的
    - name: do something to initialize mysql
      file: path=/mydata/data state=directory owner=mysql group=mysql mode=0755
    - shell: /usr/bin/mysql_install_db --datadir=/mydata/data --user=mysql creates=/mydata/data/ibdata1

    - name: copy my.cnf
      copy: src=my.cnf dest=/etc/my.cnf
      notify: 
         - restart mysql

    - name: make sure mysql is running
      service: name=mysqld state=started

    - name: make sure mysql port is open
      wait_for: 
         port: "{{ mysql_port }}"
         timeout: 10

# 这里输出了nginx/meta/main.yml中传递的变量
    - name: echo var passed by nginx 
      shell: echo "{{ hi_var }}"
      register: var_result
    - debug: msg="{{ var_result.stdout }}"

/yaml/roles/mysql/handlers/main.yml 
---
   - name: restart mysql
     service: name=mysqld state=restarted

/yaml/roles/mysql/vars/main.yml 
---
    mysql_port: 3306

以下是mariadb role中各文件的内容,和mysql大体上是一致的。注意,MySQL的my.cnf和mariadb的my.cnf默认情况下并不一样,所以需要分别提供。

/yaml/roles/mariadb/tasks/main.yml 
---
    - name: make sure mariadb is installed
      yum: name=mariadb-server state=installed

    - name: do something to initialize mariadb
      file: path=/mydata/data state=directory owner=mysql group=mysql mode=0755
    - shell: /usr/bin/mysql_install_db --datadir=/mydata/data --user=mysql creates=/mydata/data/ibdata1

    - name: copy my.cnf
      copy: src=my.cnf dest=/etc/my.cnf
      notify: 
         - restart mariadb

    - name: make sure mariadb is running
      service: name=mariadb state=started

    - name: make sure mariadb port is open
      wait_for: 
         port: "{{ mariadb_port }}"
         timeout: 10

    - name: echo var passed by nginx 
      shell: echo "{{ hi_var }}"
      register: var_result
    - debug: msg="{{ var_result.stdout }}"

/yaml/roles/mariadb/handlers/main.yml 
---
    - name: restart mariadb
      service: name=mariadb state=restarted

/yaml/roles/mariadb/vars/main.yml 
---
    mariadb_port: 3306

以下是两台机器的测试结果,一台是centos 7(192.168.100.54),一台是centos 6(192.168.100.70)。

PLAY [newhosts] *************************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [192.168.100.70]
ok: [192.168.100.54]

TASK [config the yum repo for centos 7] *************************************************
skipping: [192.168.100.70]
changed: [192.168.100.54]

TASK [config the yum repo for centos 6] *************************************************
skipping: [192.168.100.54]
changed: [192.168.100.70]

TASK [mysql : make sure mysql is installed] *********************************************
skipping: [192.168.100.54]
changed: [192.168.100.70]

TASK [mysql : do something to initialize mysql] *****************************************
skipping: [192.168.100.54]
changed: [192.168.100.70]

TASK [mysql : command] ******************************************************************
skipping: [192.168.100.54]
changed: [192.168.100.70]

TASK [mysql : copy my.cnf] **************************************************************
skipping: [192.168.100.54]
changed: [192.168.100.70]

TASK [mysql : make sure mysql is running] ***********************************************
skipping: [192.168.100.54]
changed: [192.168.100.70]

TASK [mysql : make sure mysql port is open] *********************************************
skipping: [192.168.100.54]
ok: [192.168.100.70]

TASK [mysql : echo var passed by nginx] *************************************************
skipping: [192.168.100.54]
changed: [192.168.100.70]

TASK [mysql : debug] ********************************************************************
skipping: [192.168.100.54]
ok: [192.168.100.70] => {
    "changed": false, 
    "msg": "hello mysql"
}

TASK [mariadb : make sure mariadb is installed] *****************************************
skipping: [192.168.100.70]
changed: [192.168.100.54]

TASK [mariadb : do something to initialize mariadb] *************************************
skipping: [192.168.100.70]
changed: [192.168.100.54]

TASK [mariadb : command] ****************************************************************
skipping: [192.168.100.70]
changed: [192.168.100.54]

TASK [mariadb : copy my.cnf] ************************************************************
skipping: [192.168.100.70]
changed: [192.168.100.54]

TASK [mariadb : make sure mariadb is running] *******************************************
skipping: [192.168.100.70]
changed: [192.168.100.54]

TASK [mariadb : make sure mariadb port is open] *****************************************
skipping: [192.168.100.70]
ok: [192.168.100.54]

TASK [mariadb : echo var passed by nginx] ***********************************************
skipping: [192.168.100.70]
changed: [192.168.100.54]

TASK [mariadb : debug] ******************************************************************
skipping: [192.168.100.70]
ok: [192.168.100.54] => {
    "changed": false, 
    "msg": "hello mysql"
}

TASK [nginx : make sure nginx state is installed] ***************************************
changed: [192.168.100.54]
changed: [192.168.100.70]

TASK [nginx : template nginx.conf] ******************************************************
ok: [192.168.100.70]
changed: [192.168.100.54]

TASK [nginx : copy index.html] **********************************************************
changed: [192.168.100.70]
changed: [192.168.100.54]

TASK [nginx : make sure nginx service is running] ***************************************
changed: [192.168.100.54]
changed: [192.168.100.70]

TASK [nginx : make sure port is open] ***************************************************
ok: [192.168.100.70]
ok: [192.168.100.54]

RUNNING HANDLER [mysql : restart mysql] *************************************************
changed: [192.168.100.70]

RUNNING HANDLER [mariadb : restart mariadb] *********************************************
changed: [192.168.100.54]

RUNNING HANDLER [nginx : restart nginx] *************************************************
changed: [192.168.100.54]

TASK [command] **************************************************************************
changed: [192.168.100.54]
changed: [192.168.100.70]

TASK [debug] ****************************************************************************
ok: [192.168.100.54] => {
    "changed": false, 
    "msg": "deploy nginx/mysql over"
}
ok: [192.168.100.70] => {
    "changed": false, 
    "msg": "deploy nginx/mysql over"
}

PLAY RECAP ******************************************************************************
192.168.100.54             : ok=19   changed=14   unreachable=0    failed=0   
192.168.100.70             : ok=18   changed=12   unreachable=0    failed=0

相信看过上面的roles组织示例,对roles的用法和playbook就有了较深的认识。其实,ansible有一个网站专门存放了一大堆的playbook,算是playbook仓库吧。可以下载下来稍作修改就能使用,即使不使用,借鉴他们的写法也是很值得的。地址:ansible galaxy

另外,根据不同标准组织role可能会让playbook写起来更容易,例如上面的示例中,按照发行版来划分role比上面按照安装软件类型划分可能会更简单些。当然,如果在inventory中就划分好centos 6和centos 7也是可以的。哪种更方便、复用性更好就需要自行考虑了。

回到系列文章大纲:

yaml语法

  • 大小写敏感
  • 使用缩进表示层级关系(只能空格不能使用tab)
  • yaml文件"---"作为文档的开始

yaml支持的数据结构

威尼斯国际官方网站 7

 

yaml变量的应用

威尼斯国际官方网站 8

 

转载请注明出处:

playbook变量

  1. playbook的yaml文件中的定义变量赋值
  2. --extra-vars执行参数赋给变量 

 示例:

devops@devops-virtual-machine:/etc/ansible$ cat f1.yml
---
- hosts : 192.168.56.11
  remote_user : root
  #  vars :           # 注册这两行
          #          touch_file : devops.file
  tasks :
          - name : touch file
            shell: "touch /tmp/{{touch_file}}"


# 执行
devops@devops-virtual-machine:/etc/ansible$ ansible-playbook ./f1.yml --extra-vars "touch_file=json2"

PLAY [192.168.56.11] ***********************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.56.11]

TASK [touch file] **************************************************************************************************************
 [WARNING]: Consider using file module with state=touch rather than running touch

changed: [192.168.56.11]

PLAY RECAP *********************************************************************************************************************
192.168.56.11              : ok=2    changed=1    unreachable=0    failed=0

查看执行结果

devops@devops-virtual-machine:/etc/ansible$ ansible  all -a 'ls /tmp'
192.168.56.11 | SUCCESS | rc=0 >>
devops.file
json2

  3、在文件中定义变量

在资产清单中定义变量

威尼斯国际官方网站 9威尼斯国际官方网站 10

devops@devops-virtual-machine:/etc/ansible$ cat /etc/ansible/hosts
[test_group1]
#192.168.56.11:22 ansible_ssh_user=root ansible_ssh_pass='1234567'
#192.168.56.11:22 ansible_ssh_user=root ansible_ssh_key_file=/home/devops/.ssh/id_rsa
192.168.56.11:22 ansible_ssh_user=root


# 添加两行内容如下: 当f1.yaml执行时会引用(touch_file)这个变量
[test_group1:vars]
touch_file=json3

# 执行
devops@devops-virtual-machine:/etc/ansible$ ansible-playbook ./f1.yml

PLAY [192.168.56.11] ***********************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.56.11]

TASK [touch file] **************************************************************************************************************
 [WARNING]: Consider using file module with state=touch rather than running touch

changed: [192.168.56.11]

PLAY RECAP *********************************************************************************************************************
192.168.56.11              : ok=2    changed=1    unreachable=0    failed=0


# 查看执行服务器(192.168.56.11 )上是否有json3文件
devops@devops-virtual-machine:/etc/ansible$ ansible  all -a 'ls /tmp'
192.168.56.11 | SUCCESS | rc=0 >>
json2
json3

示例

  4、注册变量

register关键字可以存储指定的命令的输出结果到一个自定义的变量中

- name: get time

  command:date

  register:date_output

威尼斯国际官方网站 11威尼斯国际官方网站 12

devops@devops-virtual-machine:/etc/ansible$ cat f4.yml
---
- hosts : 192.168.56.11
  remote_user : root
  vars :
      touch_file : devops.file
  tasks :
      - name : get date
        command : date              # 执行date命令
        register : date_output      # 把date的执行结果赋值给date_output
      - name : touch file
        shell : "touch /tmp/{{touch_file}}"
      - name : echo date_output
        shell : "echo {{date_output.stdout}}>/tmp/{{touch_file}}"

# 执行 加vvv显示详细信息
devops@devops-virtual-machine:/etc/ansible$ ansible-playbook ./f4.yml -vvv
ansible-playbook 2.4.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/devops/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/dist-packages/ansible-2.4.1.0-py3.6.egg/ansible
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.6.5 (default, Apr  1 2018, 05:46:30) [GCC 7.3.0]
Using /etc/ansible/ansible.cfg as config file
Parsed /etc/ansible/hosts inventory source with ini plugin

PLAYBOOK: f4.yml ***********************************************************************************************
1 plays in ./f4.yml

PLAY [192.168.56.11] *******************************************************************************************

TASK [Gathering Facts] *****************************************************************************************
Using module file /usr/local/lib/python3.6/dist-packages/ansible-2.4.1.0-py3.6.egg/ansible/modules/system/setup.py
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<192.168.56.11> (0, b'/rootn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231 `" && echo ansible-tmp-1531396830.9463239-175629470926231="` echo /root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231 `" ) && sleep 0'"'"''
<192.168.56.11> (0, b'ansible-tmp-1531396830.9463239-175629470926231=/root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231n', b'')
<192.168.56.11> PUT /tmp/tmpihpjzcgr TO /root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231/setup.py
<192.168.56.11> SSH: EXEC sftp -b - -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 '[192.168.56.11]'
<192.168.56.11> (0, b'sftp> put /tmp/tmpihpjzcgr /root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231/setup.pyn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231/ /root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231/setup.py && sleep 0'"'"''
<192.168.56.11> (0, b'', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 -tt 192.168.56.11 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231/setup.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1531396830.9463239-175629470926231/" > /dev/null 2>&1 && sleep 0'"'"''
<192.168.56.11> (0, b'rn{"invocation": {"module_args": {"filter": "*", "gather_subset": ["all"], "fact_path": "/etc/ansible/facts.d", "gather_timeout": 10}}, "ansible_facts": {"ansible_product_serial": "VMware-56 4d ba ea 2a 14 bd 0e-90 3f 06 a4 d2 a0 10 ca", "ansible_form_factor": "Other", "ansible_distribution_file_parsed": true, "ansible_fips": false, "ansible_service_mgr": "systemd", "ansible_user_id": "root", "ansible_selinux_python_present": true, "ansible_userspace_bits": "64", "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDvGRGyqSELPCWRxOyhXtCk8HvSnKH82paTv3gVgfkmD9wI7eVXXQDXOoTXYJZzKK5bDy3fsSZg7BpHDLysHff1fUh3oexfzUepT440VAonQl9cWSdUgSQUPZdJuj+o+9teIbkT4yWxh+ou+59uC1z0zwWWs99aIn4Ul/RdAjJJr0O+iTYcdHsnupAxf9T/bpsW49cTRXhhzkQW9gUpyanfVU94Y+cKb/D178V//zL4/Km/90WSFQGMW0xWTSxh1QbqZge639K3BR/wL5VUJhy8Nv6HQPgV9aTkCLNERk4sjrMWQWP4jsT0VPQ0VpS7iE7GQZrbPx3qE/49vcQNIwG3", "gather_subset": ["all"], "ansible_real_user_id": 0, "ansible_architecture": "x86_64", "ansible_local": {}, "ansible_distribution_version": "7.3.1611", "ansible_domain": "example.com", "ansible_distribution_file_path": "/etc/redhat-release", "ansible_user_shell": "/bin/bash", "ansible_date_time": {"weekday_number": "4", "iso8601_basic_short": "20180712T200057", "tz": "CST", "weeknumber": "28", "hour": "20", "year": "2018", "minute": "00", "tz_offset": "+0800", "month": "07", "epoch": "1531396857", "iso8601_micro": "2018-07-12T12:00:57.933420Z", "weekday": "\u661f\u671f\u56db", "time": "20:00:57", "date": "2018-07-12", "iso8601": "2018-07-12T12:00:57Z", "day": "12", "iso8601_basic": "20180712T200057933342", "second": "57"}, "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIDG1zxZJmUXAcaboS6in1sWqmzxiu0mqwHsr0wzF2khq", "ansible_processor_cores": 1, "ansible_virtualization_role": "guest", "ansible_distribution_file_variety": "RedHat", "ansible_env": {"LANG": "zh_CN.UTF-8", "TERM": "xterm-256color", "SHELL": "/bin/bash", "XDG_RUNTIME_DIR": "/run/user/0", "SHLVL": "2", "SSH_TTY": "/dev/pts/0", "HOME": "/root", "SSH_CLIENT": "192.168.56.133 44790 22", "LESSOPEN": "||/usr/bin/lesspipe.sh %s", "PWD": "/root", "LOGNAME": "root", "USER": "root", "MAIL": "/var/mail/root", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin", "LS_COLORS": "rs=0:di=38;5;27:ln=38;5;51:mh=44;38;5;15:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=05;48;5;232;38;5;15:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;34:*.tar=38;5;9:*.tgz=38;5;9:*.arc=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lha=38;5;9:*.lz4=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.tzo=38;5;9:*.t7z=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.Z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lrz=38;5;9:*.lz=38;5;9:*.lzo=38;5;9:*.xz=38;5;9:*.bz2=38;5;9:*.bz=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.war=38;5;9:*.ear=38;5;9:*.sar=38;5;9:*.rar=38;5;9:*.alz=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.cab=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.webm=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.axa=38;5;45:*.oga=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:", "XDG_SESSION_ID": "5", "_": "/usr/bin/python", "SSH_CONNECTION": "192.168.56.133 44790 192.168.56.11 22"}, "ansible_effective_group_id": 0, "ansible_bios_version": "6.00", "ansible_processor": ["0", "GenuineIntel", "Intel(R) Core(TM) i5-7267U CPU @ 3.10GHz"], "ansible_virtualization_type": "VMware", "ansible_lo": {"features": {"tx_checksum_ipv4": "off [fixed]", "generic_receive_offload": "on", "tx_checksum_ipv6": "off [fixed]", "tx_scatter_gather_fraglist": "on [fixed]", "rx_all": "off [fixed]", "highdma": "on [fixed]", "rx_fcs": "off [fixed]", "tx_lockless": "on [fixed]", "tx_tcp_ecn_segmentation": "on", "tx_tcp6_segmentation": "on", "tx_gso_robust": "off [fixed]", "tx_ipip_segmentation": "off [fixed]", "tx_checksumming": "on", "vlan_challenged": "on [fixed]", "loopback": "on [fixed]", "fcoe_mtu": "off [fixed]", "scatter_gather": "on", "tx_checksum_sctp": "on [fixed]", "tx_vlan_stag_hw_insert": "off [fixed]", "rx_vlan_stag_hw_parse": "off [fixed]", "rx_vlan_stag_filter": "off [fixed]", "large_receive_offload": "off [fixed]", "tx_scatter_gather": "on [fixed]", "rx_checksumming": "on [fixed]", "tx_tcp_segmentation": "on", "netns_local": "on [fixed]", "busy_poll": "off [fixed]", "generic_segmentation_offload": "on", "tx_udp_tnl_segmentation": "off [fixed]", "tcp_segmentation_offload": "on", "l2_fwd_offload": "off [fixed]", "rx_vlan_offload": "off [fixed]", "ntuple_filters": "off [fixed]", "tx_vlan_offload": "off [fixed]", "tx_nocache_copy": "off [fixed]", "tx_mpls_segmentation": "off [fixed]", "udp_fragmentation_offload": "on", "tx_sctp_segmentation": "on", "tx_sit_segmentation": "off [fixed]", "tx_checksum_fcoe_crc": "off [fixed]", "hw_tc_offload": "off [fixed]", "tx_checksum_ip_generic": "on [fixed]", "tx_fcoe_segmentation": "off [fixed]", "rx_vlan_filter": "off [fixed]", "receive_hashing": "off [fixed]", "tx_gre_segmentation": "off [fixed]"}, "hw_timestamp_filters": [], "mtu": 65536, "device": "lo", "promisc": false, "timestamping": ["rx_software", "software"], "ipv4": {"broadcast": "host", "netmask": "255.0.0.0", "network": "127.0.0.0", "address": "127.0.0.1"}, "ipv6": [{"scope": "host", "prefix": "128", "address": "::1"}], "active": true, "type": "loopback"}, "ansible_memtotal_mb": 976, "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPb+x6CxAv1fn1DdrTK9Gn1AetZc+7Z1fNOmHTKK5YLW9AcE1dNj7ch7XzP98BpgJjkwuqig3TzYuzSajNi7qVg=", "ansible_device_links": {"masters": {"sda2": ["dm-0", "dm-1"]}, "labels": {"sr0": ["CentOS\\x207\\x20x86_64"]}, "ids": {"sr0": ["ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"], "sda2": ["lvm-pv-uuid-6PpuNw-P0Sl-vgrG-eph3-vPgV-80rS-kVO4nk"], "dm-0": ["dm-name-cl-root", "dm-uuid-LVM-yZVSxca2orueczI165YImVDpRd6Uy7HQ7Qpv8yMY9esqgrnFTcf8dbPKaZ5DK7j1"], "dm-1": ["dm-name-cl-swap", "dm-uuid-LVM-yZVSxca2orueczI165YImVDpRd6Uy7HQJsBOsjYPBRT6yKFLgQcHw9IcENdrUaD0"]}, "uuids": {"sr0": ["2016-12-05-13-55-45-00"], "sda1": ["bd203c5e-8ff1-4060-bcaf-990e2ccb61c1"], "dm-0": ["8d886d43-1ef5-451a-951c-4170c89c9412"], "dm-1": ["2b2df9d8-6c15-4c0e-a4cb-9e25edbf17b8"]}}, "ansible_default_ipv4": {"macaddress": "00:0c:29:a0:10:ca", "network": "192.168.56.0", "mtu": 1500, "broadcast": "192.168.56.255", "alias": "eth0", "netmask": "255.255.255.0", "address": "192.168.56.11", "interface": "eth0", "type": "ether", "gateway": "192.168.56.2"}, "ansible_swapfree_mb": 2047, "ansible_default_ipv6": {}, "ansible_distribution_release": "Core", "ansible_system_vendor": "VMware, Inc.", "ansible_apparmor": {"status": "disabled"}, "ansible_cmdline": {"LANG": "en_US.UTF-8", "BOOT_IMAGE": "/vmlinuz-3.10.0-514.el7.x86_64", "quiet": true, "net.ifnames": "0", "rhgb": true, "biosdevname": "0", "crashkernel": "auto", "rd.lvm.lv": "cl/swap", "ro": true, "root": "/dev/mapper/cl-root"}, "ansible_effective_user_id": 0, "ansible_user_gid": 0, "ansible_selinux": {"status": "disabled"}, "ansible_product_version": "None", "ansible_os_family": "RedHat", "ansible_userspace_architecture": "x86_64", "ansible_product_uuid": "EABA4D56-142A-0EBD-903F-06A4D2A010CA", "ansible_system": "Linux", "ansible_pkg_mgr": "yum", "ansible_memfree_mb": 192, "ansible_devices": {"sr0": {"scheduler_mode": "cfq", "rotational": "1", "vendor": "NECVMWar", "sectors": "8554496", "links": {"masters": [], "labels": ["CentOS\\x207\\x20x86_64"], "ids": ["ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"], "uuids": ["2016-12-05-13-55-45-00"]}, "sas_device_handle": null, "sas_address": null, "virtual": 1, "host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)", "sectorsize": "2048", "removable": "1", "support_discard": "0", "model": "VMware IDE CDR10", "partitions": {}, "holders": [], "size": "16.32 GB"}, "sda": {"scheduler_mode": "deadline", "rotational": "1", "vendor": "VMware,", "sectors": "104857600", "links": {"masters": [], "labels": [], "ids": [], "uuids": []}, "sas_device_handle": null, "sas_address": null, "virtual": 1, "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)", "sectorsize": "512", "removable": "0", "support_discard": "0", "model": "VMware Virtual S", "partitions": {"sda2": {"sectorsize": 512, "uuid": null, "links": {"masters": ["dm-0", "dm-1"], "labels": [], "ids": ["lvm-pv-uuid-6PpuNw-P0Sl-vgrG-eph3-vPgV-80rS-kVO4nk"], "uuids": []}, "sectors": "102758400", "start": "2099200", "holders": ["cl-root", "cl-swap"], "size": "49.00 GB"}, "sda1": {"sectorsize": 512, "uuid": "bd203c5e-8ff1-4060-bcaf-990e2ccb61c1", "links": {"masters": [], "labels": [], "ids": [], "uuids": ["bd203c5e-8ff1-4060-bcaf-990e2ccb61c1"]}, "sectors": "2097152", "start": "2048", "holders": [], "size": "1.00 GB"}}, "holders": [], "size": "50.00 GB"}, "dm-0": {"scheduler_mode": "", "rotational": "1", "vendor": null, "sectors": "98549760", "links": {"masters": [], "labels": [], "ids": ["dm-name-cl-root", "dm-uuid-LVM-yZVSxca2orueczI165YImVDpRd6Uy7HQ7Qpv8yMY9esqgrnFTcf8dbPKaZ5DK7j1"], "uuids": ["8d886d43-1ef5-451a-951c-4170c89c9412"]}, "sas_device_handle": null, "sas_address": null, "virtual": 1, "host": "", "sectorsize": "512", "removable": "0", "support_discard": "0", "model": null, "partitions": {}, "holders": [], "size": "46.99 GB"}, "dm-1": {"scheduler_mode": "", "rotational": "1", "vendor": null, "sectors": "4194304", "links": {"masters": [], "labels": [], "ids": ["dm-name-cl-swap", "dm-uuid-LVM-yZVSxca2orueczI165YImVDpRd6Uy7HQJsBOsjYPBRT6yKFLgQcHw9IcENdrUaD0"], "uuids": ["2b2df9d8-6c15-4c0e-a4cb-9e25edbf17b8"]}, "sas_device_handle": null, "sas_address": null, "virtual": 1, "host": "", "sectorsize": "512", "removable": "0", "support_discard": "0", "model": null, "partitions": {}, "holders": [], "size": "2.00 GB"}}, "ansible_user_uid": 0, "ansible_lvm": {"pvs": {"/dev/sda2": {"free_g": "0.00", "size_g": "49.00", "vg": "cl"}}, "lvs": {"root": {"size_g": "46.99", "vg": "cl"}, "swap": {"size_g": "2.00", "vg": "cl"}}, "vgs": {"cl": {"free_g": "0.00", "size_g": "49.00", "num_lvs": "2", "num_pvs": "1"}}}, "ansible_distribution": "CentOS", "ansible_user_dir": "/root", "ansible_dns": {"nameservers": ["192.168.56.2"]}, "ansible_distribution_major_version": "7", "module_setup": true, "ansible_processor_count": 1, "ansible_hostname": "linux-node1", "ansible_processor_vcpus": 1, "ansible_swaptotal_mb": 2047, "ansible_lsb": {}, "ansible_real_group_id": 0, "ansible_bios_date": "05/19/2017", "ansible_all_ipv6_addresses": ["fe80::20c:29ff:fea0:10ca"], "ansible_interfaces": ["lo", "eth0"], "ansible_uptime_seconds": 695, "ansible_machine_id": "9460c222be194212b2efa3c8edde3c95", "ansible_kernel": "3.10.0-514.el7.x86_64", "ansible_memory_mb": {"real": {"total": 976, "used": 784, "free": 192}, "swap": {"cached": 0, "total": 2047, "free": 2047, "used": 0}, "nocache": {"used": 464, "free": 512}}, "ansible_user_gecos": "root", "ansible_system_capabilities_enforced": "True", "ansible_python": {"executable": "/usr/bin/python", "version": {"micro": 5, "major": 2, "releaselevel": "final", "serial": 0, "minor": 7}, "type": "CPython", "has_sslcontext": true, "version_info": [2, 7, 5, "final", 0]}, "ansible_processor_threads_per_core": 1, "ansible_fqdn": "linux-node1.example.com", "ansible_mounts": [{"block_used": 576476, "uuid": "8d886d43-1ef5-451a-951c-4170c89c9412", "size_total": 50432839680, "block_total": 12312705, "mount": "/", "block_available": 11736229, "size_available": 48071593984, "fstype": "xfs", "inode_total": 24637440, "options": "rw,relatime,attr2,inode64,noquota", "device": "/dev/mapper/cl-root", "inode_used": 57053, "block_size": 4096, "inode_available": 24580387}, {"block_used": 35407, "uuid": "bd203c5e-8ff1-4060-bcaf-990e2ccb61c1", "size_total": 1063256064, "block_total": 259584, "mount": "/boot", "block_available": 224177, "size_available": 918228992, "fstype": "xfs", "inode_total": 524288, "options": "rw,relatime,attr2,inode64,noquota", "device": "/dev/sda1", "inode_used": 330, "block_size": 4096, "inode_available": 523958}], "ansible_eth0": {"macaddress": "00:0c:29:a0:10:ca", "features": {"tx_checksum_ipv4": "off [fixed]", "generic_receive_offload": "on", "tx_checksum_ipv6": "off [fixed]", "tx_scatter_gather_fraglist": "off [fixed]", "rx_all": "off", "highdma": "off [fixed]", "rx_fcs": "off", "tx_lockless": "off [fixed]", "tx_tcp_ecn_segmentation": "off [fixed]", "tx_tcp6_segmentation": "off [fixed]", "tx_gso_robust": "off [fixed]", "tx_ipip_segmentation": "off [fixed]", "tx_checksumming": "on", "vlan_challenged": "off [fixed]", "loopback": "off [fixed]", "fcoe_mtu": "off [fixed]", "scatter_gather": "on", "tx_checksum_sctp": "off [fixed]", "tx_vlan_stag_hw_insert": "off [fixed]", "rx_vlan_stag_hw_parse": "off [fixed]", "rx_vlan_stag_filter": "off [fixed]", "large_receive_offload": "off [fixed]", "tx_scatter_gather": "on", "rx_checksumming": "off", "tx_tcp_segmentation": "on", "netns_local": "off [fixed]", "busy_poll": "off [fixed]", "generic_segmentation_offload": "on", "tx_udp_tnl_segmentation": "off [fixed]", "tcp_segmentation_offload": "on", "l2_fwd_offload": "off [fixed]", "rx_vlan_offload": "on", "ntuple_filters": "off [fixed]", "tx_vlan_offload": "on [fixed]", "tx_nocache_copy": "off", "tx_mpls_segmentation": "off [fixed]", "udp_fragmentation_offload": "off [fixed]", "tx_sctp_segmentation": "off [fixed]", "tx_sit_segmentation": "off [fixed]", "tx_checksum_fcoe_crc": "off [fixed]", "hw_tc_offload": "off [fixed]", "tx_checksum_ip_generic": "on", "tx_fcoe_segmentation": "off [fixed]", "rx_vlan_filter": "on [fixed]", "receive_hashing": "off [fixed]", "tx_gre_segmentation": "off [fixed]"}, "type": "ether", "pciid": "0000:02:01.0", "module": "e1000", "mtu": 1500, "device": "eth0", "promisc": false, "timestamping": ["tx_software", "rx_software", "software"], "ipv4": {"broadcast": "192.168.56.255", "netmask": "255.255.255.0", "network": "192.168.56.0", "address": "192.168.56.11"}, "ipv6": [{"scope": "link", "prefix": "64", "address": "fe80::20c:29ff:fea0:10ca"}], "active": true, "speed": 1000, "hw_timestamp_filters": []}, "ansible_nodename": "linux-node1.example.com", "ansible_product_name": "VMware Virtual Platform", "ansible_machine": "x86_64", "ansible_system_capabilities": ["cap_chown", "cap_dac_override", "cap_dac_read_search", "cap_fowner", "cap_fsetid", "cap_kill", "cap_setgid", "cap_setuid", "cap_setpcap", "cap_linux_immutable", "cap_net_bind_service", "cap_net_broadcast", "cap_net_admin", "cap_net_raw", "cap_ipc_lock", "cap_ipc_owner", "cap_sys_module", "cap_sys_rawio", "cap_sys_chroot", "cap_sys_ptrace", "cap_sys_pacct", "cap_sys_admin", "cap_sys_boot", "cap_sys_nice", "cap_sys_resource", "cap_sys_time", "cap_sys_tty_config", "cap_mknod", "cap_lease", "cap_audit_write", "cap_audit_control", "cap_setfcap", "cap_mac_override", "cap_mac_admin", "cap_syslog", "35", "36+ep"], "ansible_all_ipv4_addresses": ["192.168.56.11"], "ansible_python_version": "2.7.5"}}rn', b'Connection to 192.168.56.11 closed.rn')
ok: [192.168.56.11]
META: ran handlers

TASK [get date] ************************************************************************************************
task path: /etc/ansible/f4.yml:7
Using module file /usr/local/lib/python3.6/dist-packages/ansible-2.4.1.0-py3.6.egg/ansible/modules/commands/command.py
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<192.168.56.11> (0, b'/rootn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949 `" && echo ansible-tmp-1531396858.131543-153072002529949="` echo /root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949 `" ) && sleep 0'"'"''
<192.168.56.11> (0, b'ansible-tmp-1531396858.131543-153072002529949=/root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949n', b'')
<192.168.56.11> PUT /tmp/tmpvtmja2wo TO /root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949/command.py
<192.168.56.11> SSH: EXEC sftp -b - -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 '[192.168.56.11]'
<192.168.56.11> (0, b'sftp> put /tmp/tmpvtmja2wo /root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949/command.pyn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949/ /root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949/command.py && sleep 0'"'"''
<192.168.56.11> (0, b'', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 -tt 192.168.56.11 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949/command.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1531396858.131543-153072002529949/" > /dev/null 2>&1 && sleep 0'"'"''
<192.168.56.11> (0, b'rn{"changed": true, "end": "2018-07-12 20:00:58.966945", "stdout": "2018\u5e74 07\u6708 12\u65e5 \u661f\u671f\u56db 20:00:58 CST", "cmd": ["date"], "rc": 0, "start": "2018-07-12 20:00:58.964445", "stderr": "", "delta": "0:00:00.002500", "invocation": {"module_args": {"warn": true, "executable": null, "_uses_shell": false, "_raw_params": "date", "removes": null, "creates": null, "chdir": null, "stdin": null}}}rn', b'Connection to 192.168.56.11 closed.rn')
changed: [192.168.56.11] => {
    "changed": true,
    "cmd": [
        "date"
    ],
    "delta": "0:00:00.002500",
    "end": "2018-07-12 20:00:58.966945",
    "failed": false,
    "invocation": {
        "module_args": {
            "_raw_params": "date",
            "_uses_shell": false,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "warn": true
        }
    },
    "rc": 0,
    "start": "2018-07-12 20:00:58.964445",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "2018年 07月 12日 星期四 20:00:58 CST",
    "stdout_lines": [
        "2018年 07月 12日 星期四 20:00:58 CST"
    ]
}

TASK [touch file] **********************************************************************************************
task path: /etc/ansible/f4.yml:10
Using module file /usr/local/lib/python3.6/dist-packages/ansible-2.4.1.0-py3.6.egg/ansible/modules/commands/command.py
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<192.168.56.11> (0, b'/rootn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299 `" && echo ansible-tmp-1531396858.9646013-174118352784299="` echo /root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299 `" ) && sleep 0'"'"''
<192.168.56.11> (0, b'ansible-tmp-1531396858.9646013-174118352784299=/root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299n', b'')
<192.168.56.11> PUT /tmp/tmpo3kyh0pw TO /root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299/command.py
<192.168.56.11> SSH: EXEC sftp -b - -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 '[192.168.56.11]'
<192.168.56.11> (0, b'sftp> put /tmp/tmpo3kyh0pw /root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299/command.pyn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299/ /root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299/command.py && sleep 0'"'"''
<192.168.56.11> (0, b'', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 -tt 192.168.56.11 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299/command.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1531396858.9646013-174118352784299/" > /dev/null 2>&1 && sleep 0'"'"''
<192.168.56.11> (0, b'rn{"changed": true, "end": "2018-07-12 20:00:59.818106", "stdout": "", "cmd": "touch /tmp/devops.file", "rc": 0, "start": "2018-07-12 20:00:59.815108", "stderr": "", "delta": "0:00:00.002998", "invocation": {"module_args": {"warn": true, "executable": null, "_uses_shell": true, "_raw_params": "touch /tmp/devops.file", "removes": null, "creates": null, "chdir": null, "stdin": null}}, "warnings": ["Consider using file module with state=touch rather than running touch"]}rn', b'Connection to 192.168.56.11 closed.rn')
 [WARNING]: Consider using file module with state=touch rather than running touch

changed: [192.168.56.11] => {
    "changed": true,
    "cmd": "touch /tmp/devops.file",
    "delta": "0:00:00.002998",
    "end": "2018-07-12 20:00:59.818106",
    "failed": false,
    "invocation": {
        "module_args": {
            "_raw_params": "touch /tmp/devops.file",
            "_uses_shell": true,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "warn": true
        }
    },
    "rc": 0,
    "start": "2018-07-12 20:00:59.815108",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "",
    "stdout_lines": []
}

TASK [echo date_output] ****************************************************************************************
task path: /etc/ansible/f4.yml:12
Using module file /usr/local/lib/python3.6/dist-packages/ansible-2.4.1.0-py3.6.egg/ansible/modules/commands/command.py
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<192.168.56.11> (0, b'/rootn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393 `" && echo ansible-tmp-1531396859.8218389-268766387785393="` echo /root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393 `" ) && sleep 0'"'"''
<192.168.56.11> (0, b'ansible-tmp-1531396859.8218389-268766387785393=/root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393n', b'')
<192.168.56.11> PUT /tmp/tmp__kyifmp TO /root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393/command.py
<192.168.56.11> SSH: EXEC sftp -b - -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 '[192.168.56.11]'
<192.168.56.11> (0, b'sftp> put /tmp/tmp__kyifmp /root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393/command.pyn', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 192.168.56.11 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393/ /root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393/command.py && sleep 0'"'"''
<192.168.56.11> (0, b'', b'')
<192.168.56.11> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.56.11> SSH: EXEC ssh -o StrictHostKeyChecking=no -o StrictHostKeyChecking=no -o Port=22 -o 'IdentityFile="/home/devops/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=20 -tt 192.168.56.11 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393/command.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1531396859.8218389-268766387785393/" > /dev/null 2>&1 && sleep 0'"'"''
<192.168.56.11> (0, b'rn{"changed": true, "end": "2018-07-12 20:01:00.692177", "stdout": "", "cmd": "echo 2018\u5e74 07\u6708 12\u65e5 \u661f\u671f\u56db 20:00:58 CST>/tmp/devops.file", "rc": 0, "start": "2018-07-12 20:01:00.689318", "stderr": "", "delta": "0:00:00.002859", "invocation": {"module_args": {"warn": true, "executable": null, "_uses_shell": true, "_raw_params": "echo 2018\u5e74 07\u6708 12\u65e5 \u661f\u671f\u56db 20:00:58 CST>/tmp/devops.file", "removes": null, "creates": null, "chdir": null, "stdin": null}}}rn', b'Connection to 192.168.56.11 closed.rn')
changed: [192.168.56.11] => {
    "changed": true,
    "cmd": "echo 2018年 07月 12日 星期四 20:00:58 CST>/tmp/devops.file",
    "delta": "0:00:00.002859",
    "end": "2018-07-12 20:01:00.692177",
    "failed": false,
    "invocation": {
        "module_args": {
            "_raw_params": "echo 2018年 07月 12日 星期四 20:00:58 CST>/tmp/devops.file",
            "_uses_shell": true,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "warn": true
        }
    },
    "rc": 0,
    "start": "2018-07-12 20:01:00.689318",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "",
    "stdout_lines": []
}
META: ran handlers
META: ran handlers

PLAY RECAP *****************************************************************************************************
192.168.56.11              : ok=4    changed=3    unreachable=0    failed=0

# 到执行服务器上查看文件内容
[root@linux-node1 tmp]# cat devops.file
2018年 07月 12日 星期四 20:00:58 CST

示例

注:若您觉得这篇文章还不错请点击下右下角的推荐,有了您的支持才能激发作者更大的写作热情,非常感谢!

本文目录: 1.1 yaml语法和示例 1.2 ansible-playbook命令说明及playbook书写简单...

本文由威尼斯国际官方网站发布于电脑知识,转载请注明出处:【威尼斯国际官方网站】playbook模式及语法,pl

关键词: