ansible
简介
ansible是自动化运维工具,不是一个服务,可同时为多台主机安装软件。ansible不需要安装agent,部署简单,基于现有的ssh服务。是模块化的,调用特定模块,完成特定任务,支持主从模式,支持自定义模块,支持playbook,ansible是用python研发的,依赖两个组件PyYAML,python-paramiko。
安装ansible:
置好epel yum源,然后安装即可:
yum install ansible
/etc/ansible/ansible.cfg 主配置文件
/etc/ansible/hosts 主机清单
/etc/ansible/roles 角色配置文件
/usr/bin/ansible 主程序
/usr/bin/ansible-doc 文档
/usr/bin/ansible-playbook 剧本
去除ssh应答:
vim /etc/ansible/ansible.cfg host_key_checking=false
配置通信
配置SSH基于密钥方式通讯:
ansible是基于ssh配置管理、应用部署、任务执行等功能,因此需要配置ansible端基于密钥认证的方式联系各个被管理节点。
生成秘钥对:在管理端上执行如下命令
ssh-keygen -t rsa -P ''
-p 指定密码,然后会提示秘钥要保存的位置,如果是在家目录下选择默认直接回车即可。这个-P的密码会在第一次使用ansible时提示输入密码。
生成秘钥对后要将公钥部分放在每一个要被管理的主机相应目录下,包括本主机,使用命令:
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.96.130
-i 指定公钥文件位置
回车后输入这个主机的密码。
测试是否成功:
ssh 192.168.96.132 'ifconfig'
基于账户密码通讯:
如果不使用基于秘钥的方式进行通讯还可以在主机列表中定义连接主机的用户和密码。配置方式为打开 /etc/hosts 文件,在里面定义如下格式内容。
[websrvs] 192.168.96.130 ansible_ssh_user=username ansible_ssh_password=password [sbsrvs] 192.168.96.132 ansible_ssh_user=username ansible_ssh_password=password
每个主机后面都要写账号和密码。
统一配置变量:
[elk] 10.1.55.73 10.1.55.98 10.1.55.106 [elk:vars] ansible_ssh_user=root ansible_ssh_port=6033
配置主机清单
配置hosts文件:
使用ansible前要配置主机清单:/etc/ansible/hosts
192.168.96.132 [websrvs] 192.168.96.130 [sbsrvs] 192.168.96.130
主机清单的使用:
指定全部主机 all:
ansible all -m command -a 'ifconfig'
指定组名:
ansible websrvs -m command -a 'ifconfig'
-a 指明要使用的命令以及参数 a = argument
默认模块 -m command 可以省略
ansible all -a 'ifconfig'
ansible使用格式:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
例:如果执行结果是正确的则会返回绿色字体,否者返回红色字体,默认模块为command可省略。
ansible 192.168.96.132 -m command -a 'ifconfig' ansible 192.168.96.130 -m command -a 'ifconfig' ansible all -m command -a 'ifconfig' ansible all -a 'ifconfig'
-i 指定主机清单位置。如果不填写主机信息则使用-i 来指定主机的清单。
-f 为一次性连接几台,如果主机非常多无法同时连接,ansible会自动分批次进行连接,-f就是指定每次连接的个数。
-m 指定模块,默认为command模块。
args: key=value,注意:command模块要执行命令无须为key=value格式,而是直接给出要执行的命令即可。
更多信息使用 man ansible来查看。
ansible-doc文档查看命令:
使用 ansible-doc 命令可以查看响应模块文档,ansible-doc命令可以使用-h选项来查看这个命令的使用帮助。要查询某个模块的使用方法使用 -s 选项,如想查看command命令的使用方法 ansible-doc -s command 即可看到响应的帮助信息。
使用模块
ansible有各种各样的模块,使用ansible-doc -s module_name 来查看模块具体的使用方法,可以帮助我们更好的进行操作,如ping模块,ansible all -m ping,-m为指定模块名称。
执行一些命令:
ansible websrvs -a 'wget -O /tmp/xxx.rpm http://xxx.rpm'
常用模块
command模块:
command -a 'COMMAND'
默认为command模块,command模块要执行命令无须为key=value格式,直接给出要执行的命令即可。
user模块:
user -a 'name= state={present|absent} system= uid='
user模块用来创建用户,name为必须项,present必须要存在,absent表示必须要删除,-m指定模块名称,system=yes可以创建一个系统用户,即使这个命令再次执行一遍也不会多创建一个账户出来,更多选项可查看帮助。
例:
ansible websrvs -m user -a 'name=username state=present'
group模块:
group -a 'name= gid= state= system='
cron模块:
cron -a 'name= minute= hour= day= month= weekday= job= user= state='
定时任务模块,name为必须,用来描述这个任务是用来做什么的,其他可以不写,默认为星号 * ,user表示这个任务是给那个用户的,job为要执行的命令本身。
例:
ansible all -m cron -a 'name="sync time from ntpserver" minute="*/10" job="/sbin/ntpdate 192.168.96.132 &> /dev/null"'
这个例子是一个通过ansible同步时间的计划任务,可以使用crontab -l 来查看各个主机的计划任务是否存在。
例二:
ansible uat -m cron -a 'name="clear log" minute="*/30" job="bash /root/bin/clear.sh" state=present'
删除任务:
ansible uat -m cron -a 'name="clear log" minute="*/30" job="bash /root/bin/clear.sh" state=absent'
时分秒精确定制:
ansible uat -m cron -a 'name="clear log" minute="0" hour="*/1" job="bash /root/bin/clear.sh" state=present'
copy模块:
copy -a 'dest= src= mode= owner= group='
可以用来分发配置文件,dest为存放配置文件的绝对路径;src为要复制文件的位置,如果是一个目录就会进行递归复制,mode为复制文件的权限。
例:
ansible all -m copy -a 'src=/etc/fstab dest=/tmp/fstab.tmp mode=600'
playbook:批量拷贝文件
- name: "copy files" copy: src: "{{item.src}}" dest: "{{item.dest}}" owner: root group: root mode: 775 with_items: - {src: "/home/dist.zip",dest: "/home/www/admin/"} - {src: "/home/www/dist.zip",dest: "/home/www/www/"}
把文件放进files目录:在playbook中引用是以当前目录 ./ 来引用的。
- name: "copy rpms" copy: src=./ dest=/root/rpms/
拷贝到指定位置:
- name: "copy file" copy: src=aaa.tar.gz dest=/root/bbb.tar.gz
file模块:
file -a 'path= mode= owner= group= state={directory|link|present|absent} src='
用来设置文件属性,可以用来创建目录、文件、链接,如果创建链接使用src来指定连接位置,path文件位置。
例:
ansible all -m file -a 'path=/tmp/testdir state=directory' ansible all -m file -a 'path=/tmp/fstab.link state=link src=/tmp/fstab.tmp' ansible all -m file -a 'path=/tmp/fstab.link state=absent force=yes'
playbook:
创建目录:
- name: "mkdir /usr/share/java" file: path=/usr/share/java state=directory
ping模块:ping 没有参数
ansible all -m ping
yum模块:
yum -a 'name= state={present|latest|absent}'
latest表示最新版本,name后面为要安装的软件名称,absent卸载。
例:
ansible all -m yum -a 'name=nginx state=latest'
service模块:
service -a 'name= state={started|stopped|restarted} enabled={yes|no}'
可以用于启动或关闭服务,name为服务名称,enabled是否开机启动
例:
ansible all -m service -a 'name=nginx state=started enabled=yes'
shell模块:
shell -a 'COMMAND'
可以用来设置账户密码,如果用command命令使用echo输出其实是在当前主机上输出的,而不是在目标主机上输出的。
ansible all -m shell -a 'echo qiyang | passwd --stdin qiyang'
script模块:
script -a '/path/to/script'
用来执行脚本。
ansible all -m script -a 'test.sh'
setup模块:
setup
用来收集主机数据,以便根据各个主机的情况来配置,收集来的数据可以在playbooks中直接作为变量使用。
ansible all -m setup
playbooks
预演脚本,可以将要执行的命令脚本等信息通过一个脚本编排好,然后去执行。脚本的格式如下,后缀名一般为yml,如vim test.yml,运行脚本 ansible-playbook test.yml 格式。
playbook的核心元素:
tasks:任务
variables:变量
templates:模板
handlers:处理器
roles:角色
简单示例:
- hosts: websrvs remote_user: root tasks: - name: create nginx group group: name=nginx system=yes gid=208 - hosts: dbsrvs remote_user: root tasks: - name: copy file to dbsrvs copy: src=/etc/inittab dest=/tmp/inittab.ans
角色:事先预定义好的角色/代码段,需要的时候可以直接应用在某台主机上,可以重复使用类似于函数的概念。
ansible-blaybooks:每个hosts为一个主机任务,所有主机执行完成第一个任务后再去执行第二个任务。
ansible-playbook install-nginx.yml
例1:
- hosts: websrvs # 主机名 remote_user: root # 用户名 tasks: # 任务 - name: create nginx group # 描述 group: name=nginx system=yes gid=208 - name: create nginx user user: name=nginx uid=208 group=nginx system=yes - hosts: dbsrvs remote_user: root tasks: - name: copy file to dbsrvs copy: src=/etc/inittab dest=/tmp/inittab.ans
例2:安装httpd并复制配置文件和启动服务。
- hosts: websrvs remote_user: root tasks: - name: install httpd yum: name=httpd state=latest - name: copy configure file for httpd copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf - name: start httpd service service: name=httpd state=started enabled=true
handlers:由某事件触发所执行的操作,当配置文件发生改变触发 restart httpd 事件,然后执行下面的handlers任务,注意:事件名称要一样。
例:当配置文件发生改变时会触发事件
- hosts: websrvs remote_user: root tasks: - name: install httpd yum: name=httpd state=latest - name: copy configure file for httpd copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd # 当配置文件发生变化时,则执行名称为“restart httpd”的handles - name: start httpd service service: name=httpd state=started enabled=true handlers: # 执行这一段 - name: restart httpd service: name=httpd state=restarted
使用变量:定义变量使用vars,使用变量要用花括号将变量名括起来。这个变量还可以是ansible中的内置变量,内置变量可以使用setup模块查看到,ansible all -m setup。
- hosts: websrvs remote_user: root vars: - package: httpd # 定义变量 - service: httpd tasks: - name: install httpd yum: name={{ package }} state=latest # 使用变量 - name: copy configure file for httpd copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: name={{ service }} state=started enabled=true # 使用变量 handlers: - name: restart httpd service: name=httpd state=restarted
例2:使用内置变量
- hosts: websrvs remote_user: root tasks: - name: copy file copy: content={{ ansible_all_ipv4_addresses }} dest=/tmp/ipv4.txt
主机变量:可以在 /etc/ansible/hosts 中定义主机时为其添加主机变量,以便于在playbook中使用。
[websrvs] 192.168.96.130 http_port=80 maxRequestsPerChild=800 # 定义变量 192.168.96.132 http_port=8080 maxRequestsPerChild=900
在playbook中可以直接使用变量。
- hosts: websrvs remote_user: root tasks: - name: copy file copy: content={{ http_port }} dest=/tmp/ipv4.txt # 使用变量
组变量:
[websrvs] 192.168.96.130 http_port=80 maxRequestsPerChild=800 192.168.96.132 http_port=8080 maxRequestsPerChild=900 [websrvs:vars] ntp_server=ntp.scriptjc.com nfs_server=nfs.scriptjc.com
定义好后就可以在playbook中使用了{{ ntp_server }}。
inventory参数:
[websrvs] 192.168.96.130 ansible_ssh_user=username ansible_ssh_pass=password
条件测试:条件测试使用when关键字,这里面用到的变量 ansible_default_ipv4.address 在setup模块中可以看到。这个例子中如果when中的条件满足则在这个主机中创建用户。
- hosts: websrvs remote_user: root vars: - username: user1 tasks: - name: create user {{ username }} user: name={{ username }} state=present when: ansible_default_ipv4.address == "192.168.96.132"
迭代:
重复执行某个任务,相当于循环。这个item是固定的,每次执行就会取一个with_items下面的值。如果有多个变量可以使用json格式。
- hosts: websrvs tasks: - name: add users user: name={{ item }} state=present groups=wheel with_items: - user2 - user3
多参数循环:
- hosts: websrvs tasks: - name: create users user: name={{ item.name }} state=present groups={{ item.groups }} with_items: - { name: 'user4', groups: 'wheel' } - { name: 'user5', groups: 'root' }
在with_items下面定义了json格式的数据,这个数据会被每次循环调用一个。引用变量时写上{{ item.xxx }} 即可调用,item格式是固定的。
变量文件的使用:
创建一个vars.yml的文件:
var1: http var2: nginx
在playbook中使用变量:
- hosts: websevs remote_user: root vars_files: - vars.yml # 变量文件 tasks: - name: install package yum: name={{var1}}
templates模板:
可以在某个配置文件中使用变量,灵活定义配置文件。
1、要使用template功能首先要在 /etc/ansible/hosts 文件中定义如下主机变量:
[websrvs] 192.168.96.132 http_port=80 192.168.96.130 http_port=8080
2、定义配置文件模板,将配置文件中要动态修改的地方使用 {{ http_port }} 这样的形式修改好后保存即可,会自动替换为各自主机中定义的变量值。
3、然后编写playbook文件,将写好的配置模板写在src后面。
- hosts: websrvs remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd yum: name={{ package }} state=latest - name: copy configure file for httpd template: src=/root/conf/httpd.conf.2 dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: name={{ service }} state=started enabled=true handlers: - name: restart httpd service: name=httpd state=restarted
算术运算:
Jinja 允许你用计算值,jinja是基于python的模板引擎。这在模板中很少用到,但是为了完整性允许其存在。支持下面的 运算符:
+ 把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2 。
- 用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1 。
/ 对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }} 。
// 对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2 。
% 计算整数除法的余数。 {{ 11 % 7 }} 等于 4 。
* 用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ ‘=’ * 80 }} 会打印 80 个等号的横条。
** 取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8 。
比较操作符:
== 比较两个对象是否相等。
!= 比较两个对象是否不等。
> 如果左边大于右边,返回 true 。
>= 如果左边大于等于右边,返回 true 。
< 如果左边小于右边,返回 true 。
<= 如果左边小于等于右边,返回 true 。
逻辑运算符:
对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式:
and 如果左操作数和右操作数同为真,返回 true 。
or 如果左操作数和右操作数有一个为真,返回 true 。
not 对一个表达式取反(见下)。
(expr) 表达式组。
tags只运行部分任务:
tags标签可以让playbook自运行部分的tasks任务,而不会全部运行。
先在playbook中定义tags,如下:
- hosts: websrvs remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd yum: name={{ package }} state=latest - name: copy configure file for httpd template: src=/root/conf/httpd.conf.2 dest=/etc/httpd/conf/httpd.conf tags: # 定义tags - conf notify: - restart httpd - name: start httpd service service: name={{ service }} state=started enabled=true handlers: - name: restart httpd service: name=httpd state=restarted
定义好后可以在就可以在命令后面添加 --tags="名称" 运行部分playbook:
ansible-playbook httpd.yml --tags="conf"
roles:
roles可以重复调用剧本,可以将各个功能分别实现再组合起来,有利于管理和修改。
创建role的步骤:
(1) 创建以roles命名的目录;
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等;
(3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建;
(4) 在playbook文件中,调用各角色;
role内各目录中可用的文件:
tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;此文件可以使用include包含其它的位于此目录中的task文件;
files目录:存放由copy或script等模块调用的文件;
templates目录:template模块会自动在此目录中寻找Jinja2模板文件;
handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler;在handler中使用include包含的其它的handler文件也应该位于此目录中;
vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量;
meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;ansible 1.3及其以后的版本才支持;
default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件。
目录结构:
/root/ansible/ ├── roles │ ├── dbsrvs │ │ ├── file │ │ ├── handlers │ │ ├── meta │ │ ├── tasks │ │ ├── template │ │ └── vars │ └── websrvs │ ├── file │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── template │ └── vars │ └── main.yml └── site.yml
快速创建:
mkdir roles/redis/{tasks,templates,files} -pv
在site.yml中定义内容如下:
- hosts: 192.168.96.132 remote_user: root roles: - websrvs - hosts: 192.168.96.130 remote_user: root roles: - dbsrvs - hosts: 192.168.96.131 remote_user: root roles: - websrvs - dbsrvs
在 ansible/websrvs/tasks/main.yml 文件中定义如下内容:这个文件中只定义所有的任务。
- name: install httpd package yum: name=httpd - name: install configuration file copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf tags: - conf notify: - restart httpd - name: start httpd service: name=httpd state=started
在 ansible/websrvs/tasks/main.yml 中定义如下内容:这个文件中只定义handlers。
- name: restart httpd service: name=httpd state=restarted
执行playbook:在dbsrvs中也同样格式定义内容,定义好后运行site.yml就可以了。
批量复制文件:
- hosts: test remote_user: root tasks: - name: copy file copy: src: '{{ item.src }}' dest: '{{ item.dest }}' with_items: - { src: './demo.txt', dest: '/root/demo.txt', owner: root, group: root, mode: 755 } - { src: '', dest: '' }
Role使用模板示例:
在roles/项目名/template目录下创建模板文件:.my.cnf
[client] user={{ username }} password={{ passwd}}
在playbook中创建文件:
- name: install mysqld_exporter unarchive: src=mysqld_exporter-0.13.0.linux-amd64.tar.gz dest=/usr/local/ - name: create link file: path=/usr/local/mysqld_exporter src=/usr/local/mysqld_exporter-0.13.0.linux-amd64 state=link - name: add service file copy: src=mysqld_exporter.service dest=/usr/lib/systemd/system/ - name: add .my.cnf file template: src=.my.cnf.j2 dest=/usr/local/mysqld_exporter/.my.cnf # 模板文件和目标文件 - name: start service service: name=mysqld_exporter state=started enabled=yes
在主文件中:
- hosts: temp remote_user: root roles: - role: mysqld_exporter vars: # 定义变量,或者使用变量文件 - username: root - passwd: 123456
角色的使用:
多角色在相同组节组执行:
- hosts: - 192.168.199.18 roles: - role: mysql username: mysql # 变量写法1 tags: mysql # 为角色打标签 - role: nginx1 when: ansible_distribution_major_version == '7' # 加入判断 vars: username: nginx1 # 变量写法2 - { role: nginx2, username: nginx2 } # 多种写法
多角色在不同节点组执行:
- hosts: redis-servers roles: - redis - hosts: mysql-servers roles: - mysql - hosts: nginx-servers roles: - nginx
委派执行:指定到某些节点去执行。
委派到远程执行:
- hosts: - 192.168.1.8 tasks: - name: hostname -I command: hostname -I delegate_to: 192.168.1.18 # 实际是在这个节点上执行的
委派到当前节点执行:
- hosts: - 192.168.1.18 tasks: - name: demo local_action: command hostname -I # 实际是在当前ansible这台机器上执行的
执行一次:在一组节点中只执行一次。
- hosts: - 192.168.1.18 - 192.168.1.8 tasks: - name: demo command: hostname -I run_once: true
设置环境变量:只是临时添加环境变量以便命令的执行,并不修改系统的环境变量。
- hosts: - 192.168.1.18 tasks: - name: demo shell: demo.sh environment: PATH: /root/abc:{{ ansible_env.PATH }} # 临时添加环境变量,以便上面的脚本demo.sh执行。
等待执行:等待一段时间后再执行。
command: hostname -I wait_for: port=80 delay=10 # 等10秒,等80端口出来再执行上面的命令 command: hostname -I wait_for: path=/var/lock/file.lock state=absent # 等待直到这个文件不存在,再执行上面的命令
互相调用:下面两种写法效果相同。
include: demo.yml include_tasks: demo.yml
导入多个task文件到一个文件:
tasks1.yml:
- hosts: - 192.168.1.8 tasks: - name: hostname -I command: hostname -I
tasks2.yml:
- hosts: - 192.168.1.8 tasks: - name: hostname -I command: hostname -I
将上面两个完整的task文件导入到一个文件:
- import_playbook: tasks1.yml - import_playbook: tasks2.yml
输出脚本的执行内容:
- name: get mysql password script: scripts/getmysqlpassword.sh register: script_output - name: show mysql password debug: var: script_output.stdout_lines
输出命令行的执行内容:
- name: command shell: command register: shell_result - name: show success output debug: msg: "{{ shell_result.stdout }}" - name: show error output debug: msg: "{{ shell_result.stderr }}"
判断上一条是否执行成功:
- name: check command cfssl shell: command -v cfssl register: cfssl_installed ignore_errors: yes # 必须加上,否者执行失败后脚本停止 delegate_to: localhost - name: copy command to directory copy: src: packages/cfssl_1.6.4_linux_amd64 dest: /usr/local/bin/cfssl mode: 755 when: cfssl_installed.rc != 0 # 上一条执行失败才执行这一条 delegate_to: localhost
不输出执行结果:执行结果格式乱可通过设置no_log不输出,通过debug格式化输出
- name: tree /usr/local/bin delegate_to: 127.0.0.1 run_once: true shell: tree /usr/local/bin register: tree_stdout no_log: true # 不输出执行结果 - name: print tree result delegate_to: 127.0.0.1 run_once: true debug: var: tree_stdout.stdout_lines
根据节点的不同来执行不同的操作:
hosts:
[mysql] master.example.local ansible_host=192.168.0.52 node_type=master # 不同节点设置不同变量 slave.example.local ansible_host=192.168.0.54 node_type=slave
tasks:
- name: copy my-master.cnf.j2 to /etc/my.cnf template: src: my-master.cnf.j2 dest: /etc/my.cnf when: node_type == "master" # 判断变量来决定是否执行 - name: copy my-slave.cnf.j2 to /etc/my.cnf template: src: my-slave.cnf.j2 dest: /etc/my.cnf when: hostvars[inventory_hostname]['node_type'] == "slave" # 不同写法,效果一样
一个节点失败则全部停止:
- hosts: k8smaster become: true remote_user: root any_errors_fatal: true # 一个节点失败则全部停止 roles: - role: kubernetes vars_files: - vars.yml vars: - install_type: 'master'
检查task返回结果:
- name: check config shell: /usr/sbin/nginx -t register: check_nginx_config changed_when: - (check_nginx_config.stdout.find('successful')) # 执行结果中找到“successful”字符串则继续执行,如果没有则停止向下执行 - false # 关闭状态标记,每次执行是changed状态,changed状态字体颜色为黄,关闭后为绿色 - name: start service service: name: nginx state: started enable: yes
分批执行:
- hosts: all serial: 2 # 一次执行执行2台,所有task执行结束后再执行后面两台继续执行 #serial: "20%" 按百分比执行 gather_facts: false tasks: - name: task one command: hostname
执行task过程中修改变量:
- hosts: all tasks: - shell: echo $PATH enviroment: # 执行过程中临时修改变量 PATH: /usr/local/app/bin:{{ ansible_env.PATH }}
等待执行:
- name: task one shell: curl localhost:80 wait_for: # 等待10秒后再请求端口 port: 80 delay: 10 - name: task shell: hostname wait_for: path: /var/lock/file.lock # 等待这个文件被删除 state: absent