Playbook

4 Playbook

4.1 playbook介绍

image-20220105223257281

playbook 剧本是由一个或多个"play"组成的列表

play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的角色。Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作

Playbook 文件是采用YAML语言编写的

4.2 YAML 语言

4.2.1 YAML语言介绍

4.2.2 YAML语言特性

4.2.3 YAML语法简介

4.2.3.1 List列表
4.2.3.2 Dictionary字典

4.2.4 三种常见的数据格式

  • xml
  • json
  • yaml

4.3 Playbook的核心元素

  • Hosts 执行的远程主机列表
  • Tasks 任务集
  • Variables 内置变量或自定义变量在playbook中调用
  • Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  • tags标签 指定某条任务执行,用于选择运行palybook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常的长。此时如果确信其没有变化,就可以通过tags跳过此些代码片段

4.3.1 hosts组件

Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中

one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
websrvs:dbsrvs	# 或者,两个组的并集
websrvs:&dbsrvs	# 与,两个组的交集

案例:

- hosts: websrvs:appsrvs

4.3.2 remote_user组件

remote_user:可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户

- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: test connection
      ping:
      remote_user: magedu
      sudo: yes			# 默认sudo为root
      sudo_user: wang	# sudo为wang

4.3.3 task列表和action组件

play的主体部分是task list,task list中有一个或多个task,各个task按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task

task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致

每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出

task两种格式:

(1) action: module arguments

(2) module: arguments 建议使用

注意: shell和command模块后面跟命令,而非key=value

范例:

---
- hosts:websrvs
  remote_user: root
  
  tasks:
    - name: install httpd
      yum: name=httpd
    - name: start httpd
    service: name=httpd state=started enabled=yes

4.3.4 其它组件

某任务的状态在运行后为changed时,可通过"notify"通知给相应的handlers任务可以通过"tags"打标签,可在ansible-playbook命令上使用-t指定进行调用

4.3.5 ShellScripts VS Playbook 案例

# SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp /tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd

# Playbook实现
---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: "安装Apache"
      yum: name=httpd
    - name: "复制配置文件"
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
    - name: "复制配置文件"
      copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
    - name: "启动Apache,并设置开机启动"
      service: name=httpd state=started enabled=yes

4.4 Playbook命令

格式:

ansible-playbook <filename.yml> ... [options]

常见选项

--check -C		# 只监测可能会发生的改变,但不真正执行操作
--list-hosts	# 列出运行任务的主机
--list-tags		# 列出tag
--list-tasks	# 列出task
--limit 主机列表	# 只针对主机列表中的主机执行
-v -vv -vvv		# 显示过程

范例

ansible-playbook file.yml --check	# 只检测
ansible-playbook file.yml
ansible-playbook file.yml --limit websrvs

4.5 Playbook初步

4.5.1 利用playbook创建mysql用户

范例: mysql_user.yml

---
- hosts: dbsrvs
  remote_user: root
  gather_facts: no
  
  task:
    - {name: create group, group: name=mysql system=yes gid=306}
    - name: create user
      user: name=mysql system=yes group=mysql shell=/sbin/nologin create_home=no home=/data/mysql uid=306

4.5.2 利用playbook安装nginx

范例: install_nginx.yml

---
# install nginx
- hosts: websrvs
  remote_user: root
  gather_facts: no
  
  tasks:
    - name: add group nginx
      group: name=nginx state=present
    - name: add user nginx
      user: name=nginx state=prent group=nginx
    - name: Install Nginx
      yum: name=nginx state=present
    - name: web page
      copy: src=/data/files/index.html dest=/usr/share/nginx/html/index.html
    - name: Start Nginx
      service: name=nginx state=started enabled=yes
      

4.5.3 利用playbook安装和卸载httpd

范例: install_httpd.yml

---
# install httpd
- hosts: websrvs
  remote_user: root
  gather_facts: no
  
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: replace configure file
      copy: src=/data/file/httpd.conf dest=/etc/httpd/conf/
    - name: replace web page
      copy: src=/data/file/index.html dest=/var/www/html/
    - name: start service
      service: name=httpd state=started enabled=yes

范例: remove_httpd.yml

# remove_httpd.yml
---
- hosts: websrvs
  remote_user: root
  gather_facts: no
  
  tasks:
    - name: remove httpd package
      yum: name=httpd stated=absent
    - name: remove apache user
      user: name=apache state=absent
    - name: remove data file
      file: name=/etc/httpd state=absent
    - name: remove web html
      file: name=/var/www/html/ state=absent

4.5.4 利用playbook安装mysql

范例:安装mysql-5.6.46-linux-glibc2.12

ls -l /data/ansible/files/mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
cat /data/ansible/files/my.cnf
cat /data/ansible/files/secure_mysql.sh
#!/bin/bash
/usr/local/mysql/bin/mysql_secure_installation <<EOF

y
magedu
magedu
y
y
y
y
EOF

cat /data/ansible/install_mysql.yml
---
# install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: install packages
      yum: name=libaio,perl-Data-Dumper,perl-Getopt-Long
    - name: create mysql group
      group: name=mysql gid=306
    - name: create mysql user
      user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes create_home=no home=/data/mysql
    - name: copy tar to remote host and file mode
      unarchive: src=/data/ansible/files/mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz dest=/usr/local/ owner=root group=root
    - name: create linkfile /usr/local/mysql
      file: src=/data/ansible/files/mysql-5.6.46-linux-glibc2.12-x86_64 dest=/usr/local/mysql state=link
    - name: data dir
      shell: chdir=/usr/local/mysql/ ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
      tags: data
    - name: config my.cnf
      copy: src=/data/ansible/files/my.cnf dest=/etc/my.cnf
    - name: service script
      shell: /bin/cp /usr/local/mysql/support_files/mysql.server /etc/init.d/mysqld
    - name enable service
      shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
      tags: service
    - name: PATH variable
      copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
    - name: secure script
      script: /data/ansible/files/secure_mysql.sh
      tags: script

4.6 Playbook中使用handlers和notify

Handlers本质是task list,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。

在notify中列出的操作称为handler,也即notify中调用handler中定义的操作

---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd
    - name: ensure apache is running
      service: name=httpd state=started enabled=yes
      
  handlers:
    - name: restart httpd
      service: name=httpd state=restarted

案例:

---
- hosts: websrvs
  remote_user: root
  gather_facts: no
  
  - tasks:
    - name: add group nginx
      group: name=nginx state=present
    - name: add user nginx
      user: name=nginx state=present group=nginx
    - name: Install nginx
      yum: name=nginx state=present
    - name: config
      copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
      notify:
        - Restart Nginx
        - Check Nginx Process
  handler:
    - name: Restart Nginx
      service: name=nginx state=restarted enabled=yes
    - name: Check Nginx Process
      shell: killall -0 nginx &> /tmp/nginx.log

4.7 Playbook中使用tags组件

在playbook文件中,可以利用tags组件,为特定task指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件

案例:

vim httpd.yml
---
# tags example
- host: websrvs
  remote_user: root
  gather_facts: no
  
  tasks:
    - name: Install httpd
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: conf
    - name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes
      
ansible-playbook -t conf,service httpd.yml      

4.8 Playbook中使用变量

**变量名:**仅能由字母、数字和下划线组成,且只能以字母开头

变量定义:

varialbe=value

范例:

http_port=80

变量调用方式:

通过{{ variable_name }}调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效

变量来源:

  1. ansible的setup facts远程主机的所有变量都可直接调用
  2. 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value
  1. 在playbook文件中定义
vars:
  - var1: value1
  - var2: value2
  1. 在独立的变量YAML文件中定义
- hosts: all
  vars_files:
    - vars.yml
  1. 在/etc/ansible/hosts中定义

    主机(普通)变量:主机组中主机单独定义,优先级高于公共变量

    组(公共)变量:针对主机组中所有主机定义统一变量

  2. 在role中定义

4.8.1 使用setup模块中的变量

要求在playbook中使用,不能用ansible命令直接调用

案例:使用setup变量

---
- hosts: all
  remote_user: root
  
  tasks:
    - name: create log file
      file: name=/data/{{ ansible_nodename }}.log state=touch owner=wang mode=600
      
ansible-playbook var.yml

4.8.2 在playbook命令行中定义变量

范例:

vim var.yml
---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: install package
      yum: name={{ pkname }} state=present
      
ansible-playbook -e pkname=httpd var.yml

4.8.3 在playbook文件中定义变量

范例:

vim var3.yml
---
- hosts: websrvs
  remote_user: root
  vars:
    - username: user1
    - groupname: group1
    
  tasks:
    - name: create group
      group: name={{ groupname }} state=present
    - name: create user
      group: name={{ username }} state=present group={{ groupname }}
      
ansible-playbook -e "username=user2 groupname=group2" var3.yml

4.6.4 使用变量文件

可以在一个独立的playbook文件中定义变量,在另一个playbook文件中引用变量文件中的变量,比playbook中定义的变量优先级高

vim vars.yml
---
# variables
package_name: vsftpd
service_name: vsftpd

vim install_app.yml
---
# install app and configure
- hosts: appsrvs
  remote_user: root
  vars_files:
    - vars.yml
    
  tasks:
    - name: install package and start service 
      yum: name={{ package_name }}
      tags: install
    - name: start service
      service: name={{ service_name }} state=started enabled=yes
      
  handlers:
    - name: restart httpd servie
      service: name={{ service_name }} state=restarted

范例:

cat vars2.yml
---
var1: httpd
var2: nginx

cat var5.yml
---
- hosts: web
  remote_user: root
  vars_files:
    - /root/vars2.yml
  
  tasks:
    - name: create httpd log
      file: name=/app/{{ var1 }}.log state=touch
    - name: create nginx log
      file: name=/app/{{ var2 }}.log state=touch

4.6.5 主机清单文件中定义变量

4.6.5.1 主机变量:

在inventory主机清单文件中为指定的主机定义变量以便于在playbook中使用

范例:

[websrvs]
www1.magedu.com http_port=80 maxRequestPerChild=808
www2.magedu.com http_port=8080 maxRequestPerChild=909
4.6.5.2 组(公共)变量:

在inventory主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量

范例:

[websrvs]
www1.magedu.com
www2.magedu.com

[websrvs:vars]
ntp_server=ntp.magedu.com
nfs_server=nfs.magedu.com

范例:

vim /etc/ansible/hosts
[websrvs]
192.168.0.101 http_port=8080 hname=www1
192.168.0.102 http_port=80 hname=www2

[websrvs:vars]
http_port=808
mark="_"

ansible websrvs -m hostname -a 'name={{ hname }}{{ mark }}{{ http_port }}'

# 命令行指定变量
ansible websrvs -e http_port=8000 -m hostname -a {{ hname }}{{ mark }}{{ http_port }}'

4.9.1 jinjia2语言

网站:https://jinja.palletsprojects.com/en/2.11.x/

jinja2语言使用字面量,有下面形式:

字符串:使用单引号或双引号

数字:整数,浮点数

列表:[item1,item2,…]

元组:(item1,item2,…)

字典:{key1:value1,key2:value2,…}

布尔型:true/false

算术运算:+,-,*,/,//,%,**

比较操作:==,!=,>,>=,<,<=

逻辑运算:and,or,not

流表达式:For,If,When

Jinja2相关

字面量:

表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的Python对象。如"Hello World"

双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如42,42.23

数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在Python里,42和42.0是不一样的

算术运算:

Jinja允许用计算值。支持下面的运算符

+:把两个对象加到一起。通常对象是数字,但是如果两者是字符串或列表,你可以用这种方式来衔接它们。无论如何这都不是首选的连接字符串的方式!连接字符串见~运算符。{{ 1 + 1 }}等于 2

-:用第一个数减去第二个数。{{ 3 - 2 }}等于 1

/:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }}等于{{ 0.5 }}

//:对两个数做除法,返回整数商。{{ 20 // 7 }}等于2

%:用右边的数乘左边的操作数。{{ 11 % 7 }}等于 4

*:用右边的数乘左边的操作数。{{ 2 * 2 }}会返回4 。 也可以用于重复一个字符串多次。{{ ‘=’ * 80 }}会打印80个等号的横条

**:取左操作数的右操作数次幂。{{ 2 ** 3}}

比较操作符

== 比较两个对象是否相等

!= 比较两个对象是否不等

> 如果左边大于右边,返回true

>= 如果左边大于等于右边,返回true

< 如果左边小于右边,返回true

<= 如果左边小于等于右边,返回true

逻辑运算符

对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式

and 如果左操作数和右操作数同为真,返回true

or 如果左操作数和右操作数有一个为真,返回true

not 对一个表达式取反

(expr)表达式组

true / false true永远是true,而false始终是false

4.9.2 template

template功能:可以根据和参考模块文件,动态生成相类似的配置文件

template文件必须存放于templates目录下,且命名为.j2结尾

yaml/yml文件需和templates目录平级,目录结构如下


范例:利用template同步nginx配置文件

# 准备templates/nginx.conf.j2文件
vim temnginx.yml
---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      
ansible-playbook temnginx.yml

template变更替换

范例:

# 修改文件nginx.conf.j2
mkdir templates
vim templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};

vim temnginx2.yml
---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    - name: start service
      service: name=nginx state=started enabled=yes

ansible-playbook temnginx2.yml

template算术运算

范例:

vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**2 }};
worker_porcesses {{ ansible_processor_vcpus+2 }};

范例:

[root@ansible ansible]# cat templnginx.yml
---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: restart nginx
    - name: start service
      service: name=nginx state=started enabled=yes
  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
      
ansible-playbook tempnginx.yml --limit 10.0.0.8

4.9.3 template中使用流程控制 for 和 if

template中也可以使用流程控制 for 循环和if 条件判断,实现动态生成文件功能

范例:

# temnginx1.yml
---
- hosts: websrvs
  remote_user: root
  vars:
    nginx_vhosts:
      - listen: 8080
  tasks:
    - name: config file
      template: src=nginx2.conf.j2 dest=/data/nginx2.conf
      
# templates/nginx.conf1.j2
{% for vhost in nginx_vhosts %}
server {
  listen {{ vhost.listen }};
}
{% endfor %}

# 生成的结果
server {
  listen 8080
}

范例:

# temnginx2.yml
---
- hosts: websrvs
  remote_user: root
  vars:
    nginx_vhosts:
      - 81
      - 82
      - 83
  tasks:
    - name: template config
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      
# templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
  listen {{ vhost }};
}
{% endfor %}

# 生成的结果
server {
  listen 81
}
server {
  listen 82
}
server {
  listen 83
}

范例:

# temnginx3.yml
---
- hosts: websrvs
  remote_user: root
  vars:
    nginx_vhosts:
      - listen: 8080
  tasks:
    - name: config file
      template: src=nginx2.conf.j2 dest=/data/nginx2.conf
 
 # templates/nginx.conf3.j2
{% for vhost in nginx_vhosts %}
server {
  listen {{ vhosts.listen }}
}
{% endfor %}

# 生成的结果
server{
  listen 8080
}

范例:

# temnginx3.yml
- hosts: websrvs
  remote_user: root
  vars:
    nginx_vhosts:
      - listen: 8080
        server_name: "web1.mage.du.com"
        root: "/var/www.nginx/web1"
      - listen: 8081
        server_name: "web2.mage.du.com"
        root: "/var/www.nginx/web2"
      - listen: 8082
        server_name: "web3.mage.du.com"
        root: "/var/www.nginx/web3"
  tasks:
    - name: template config
      template: src=nginx3.conf.j2 dest=/data/nginx3.conf
      
# templates/nginx3.conf.j2
{% for vhost in nginx_vhosts %}
server {
  listen {{ vhost.listen }}
  server_name {{ vhost.server_name }}
  root {{ vhost.root }}
}
{% endfor %}

# 生成结果
server {
  listen 8080
  server_name web1.magedu.com
  root /var/www/nginx/web1
}
server {
  listen 8081
  server_name web2.magedu.com
  root /var/www/nginx/web2
}
server {
  listen 8082
  server_name web3.magedu.com
  root /var/www/nginx/web3
}

在模板文件中还可以使用if条件判断,决定是否生成相关的配置信息

范例:

# temnginx4.yml
- hosts: websrvs
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
        listen: 8080
        root: "/var/www/nginx/web1"
      - web2:
        listen: 8080
        server_name: "web2.magedu.com"
        root: "/var/www/nginx/web2"
      - web1:
        listen: 8080
        server_name: "web3.magedu.com"
        root: "/var/www/nginx/web3"
  tasks:
    - name: template config to
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      
# templates/nginx.conf4.j2
{% for vhost in nginx_vhosts %}
server{
  listen {{ vhost.listen }}
  {% if vhost.server_name is defined %}
server_name {{ vhost.server_name }}
  {% endif %}
root {{ vhost.root }}
}
{% endfor %}

# 生成的结果
server {
  listen 8080
  root /var/www/nginx/web1
}
server {
  listen 8080
  server_name web2.magedu.com
  root /var/www/nginx/web2
}
server {
  listen 8080
  server_name web3.magedu.com
  root /var/www/nginx/web3
}

4.10 playbook使用when

when语句,可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,通过在task后添加when子句即可使用条件测试,jinja2的语法格式

范例:

---
- hosts: websrvs
  remote_user: root
  
  task:
    - name: "shutdown RedHat flavored systems"
      command: /sbin/shutdown -h now
      when: ansible_os_family == "RedHat"

范例:

---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: add group nginx
      tags: user
      user: name=nginx state=present
    - name: add user nginx
      user: name=nginx state=present group=nginx
    - name: Install Nginx
      yum: name=nginx state=present
    - name: restart Nginx
      service: name=nginx state=restarted
      when: ansible_distribution_major_version == "6"

范例:

---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: install conf file to centos7
      template: src=nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == "7"
    - name: install conf file to centos6
      template: src=nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == "6"
      

4.11 playbook使用迭代with_items

迭代:当有需要重复性执行的任务时,可以使用迭代机制

对迭代项的引用,固定变量名为"item"

要在task中使用with_items给定要迭代的元素列表

列表元素格式:

  • 字符串
  • 字典

范例:

---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: add several users
      user: name={{ item }} state=present groups=wheel
      with_items:
        - testuser1
        - testuser2
# 上面语句的功能等同于下面的语句
    - name: add user testuser1
      user: name=testuser1 state=present groups=wheel
    - name: add user testuser2
      user: name=testuser2 state=present groups=wheel

范例:

---
# remove mariadb server
- hosts: appsrvs:!192.168.38.8
  remote_user: root
  
  tasks:
    - name: stop service
      shell: /etc/init.d/mysqld stop
    - name: delete files and dir
      file: path={{ item }} state=absent
      with_items:
        - /usr/local/mysql
        - /usr/local/mariadb-10.2.27-linux-x86_64
        - /etc/init.d/mysqld
        - /etc/my.cnf
        - /data/mysql
    - name: delete user
      user: name=mysql state=absent remove=yes

范例:

---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: install some packages
      yum: name={{ item }} state=present
      with_items:
        - nginx
        - memcached
        - php-fpm

范例:

---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: copy file
      copy: src={{ item }} dest=/tmp/{{ item }}
      with_items:
        - file1
        - file2
        - file3
    - name: yum install httpd
      yum: name={{ item }} state=present
      with_items:
        - apr
        - apr-util
        - httpd

**迭代嵌套子变量:**在迭代中,还可以嵌套子变量,关联多个变量在一起使用

示例:

---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: add some groups
      group: name={{ item }} state=present
      with_items:
        - nginx
        - mysql
        - apache
    - name: add some users
      user: name={{ item.name }} group={{ item.group }} home={{ item.home }} create_home=yes state=present
      with_items:
        - { name: 'nginx', group: 'nginx', home: '/data/nginx' }
        - { name: 'mysql', group: 'mysql', home: '/data/mysql' }
        - { name: 'apache', group: 'apache', home: '/data/apache' }
      # 也可以像下面这样
      with_items:
        - name: 'nginx'
          group: 'nginx'
          home: /data/nginx
        - name: 'mysql'
          group: 'mysql'
          home: /data/mysql
        - name: 'apache'
          group: 'apache'
          home: /data/apache
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值