Ansible是一个同时管理多个远程主机的软件(任何可以通过SSH协议登录的机器),因此Ansible可以管理远程虚拟机、物理机,也可以是本地主机。
一、功能组成
功能由Ansible的Core Modules来实现的,ansible是基于python语言开发的,主要由python的两个ssh处理模块:Paramiko、PyYAML模块;
1、Paramiko模块:提供SSH通信,提供安全的远程连接、命令执行和文件传输(SCP或SFTP)【现用OpenSSH】;
2、PyYAML模块:Ansible 解析 Playbook 或 Ad-Hoc 命令,确定需要调用的模块,将yaml格式的配置文件转换为python数据结构、参数等,实现yaml解析和生成;
最后通过目标主机的 Python 解释器执行模块,或者直接调用 Shell命令。
Ansible底层远程控制和输送指令的原理:Ansible 通过 SSH 协议(默认使用系统 OpenSSH,Paramiko 作为备选)连接到目标主机,再通过 PyYAML 解析 Playbook 或直接处理 Ad-Hoc 命令,确定需要调用的模块。接着,将模块代码(如 Python 脚本)和参数通过 SCP/SFTP 或 SSH 管道 动态传输到目标主机的临时目录,调用本地 Python 解释器执行。模块执行后返回 JSON 格式的结果,由控制端解析。整个过程无代理,依赖幂等性设计确保操作安全,并通过清理临时文件保证环境整洁。
二、认证方式
1、密码认证:提供主机组中主机的密码;
/etc/ansible/hosts: [backup] 中添加端口、用户、密码信息:
例:192.168.1.41 ansible-port=22 ansible-user=root ansible-password='****'
ansible-host:主机地址,即远程主机ip;
ansible-port:主机端口,设置SSH连接端口,默认22;
ansible-user:主机用户,默认SSH远程连接的用户身份;
ansible-password:用户密码,指定SSH远程主机密码;若目标ssh信息更改了,在host文件中也要更改
2、公钥认证:管理机将自身的公钥分发给想免密登录的机器,后续再次操作目标机器时,就直接进行ssh的公钥认证,可以免密直接远程执行;
例:ssh-copy-id root@192.168.1.31:用于将本地的 SSH 公钥复制到远程服务root用户的~/.ssh/authorized_keys文件中
ssh-copy-id: 命令名,用于复制 SSH 公钥。
root: 远程主机上的用户名,这里是 root 用户。
192.168.1.31: 远程主机的 IP 地址。
【这样配置所有机器的公钥一键分发,就可以实现all所有主机的远程命令执行】
【原理】:用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
3、认证实现:
a、密钥生成:ssh-keygen -t rsa -b 4096
作用: 生成一对4096位的RSA密钥(私钥~/.ssh/id_rsa和公钥~/.ssh/id_rsa.pub)-t 指定密钥类型(如rsa、ed25519等),-b指定密钥长度
或者:
【生成密钥】ssh-keygen -t ed25519 【默认存在于/root/.ssh中】
【免密登录】ssh-copy-id -i /root/.ssh/id_ed25519.pub root@remote_ip
b、指纹确认:当客户端首次连接到SSH服务器时,服务器会将其指纹(公钥的Hash值)发送给客户端,客户端会提示接受指纹并保存在.ssh/known_hosts文件中。之后连接,客户端将接收到的指纹与它文件中已知并信任的指纹进行比较,以防止中间人攻击。
c、三种实现方案:
方案一:已经基于ssh完成了指纹确认,一键分发公钥,实现批量免密登录,再执行ansible命令;
方案二:手动ssh连接,确认指纹后,再执行ansible命令;
方案三:直接忽略指纹确认,在/etc/ansible/hosts主机清单文件中定义好ssh连接配置参数【最简单】。
三、两种执行方式
1、Ad-hoc命令行模式【适用于临时或者较小的需求】:相当于临时命令,临时的看下远程机器的内存信息或者临时的批量分发一个配置文件等。
ansible windows -m command -a "hostname"
[命令] [主机组名] [指定模块参数] [模块名] [指定模块的执行动作参数] [批量执行的操作]
例如:ansible web -m shell -a "free -m"
指定web组,指定shell模块,然后执行free -m,即让一组服务器都去执行free -m命令,并将结果返回;
ansible主机分组、批量操作 ,可以多台主机放在一个组并命组名,如[webserver]为web7、8、9的组;若为all,则表示操作所有的机器;
2、playbook【剧本】模式【适用于大需求、部署软件、标准化等】:
先在/etc/ansible/ansible.cfg配置文件中添加参数:
stdout_callback = json【用于控制输出格式,指定输出格式为JSON】;
bin_ansible_callbacks = True【二进制回调插件,允许Ansible使用非文本输出,如二进制数据】。
[root@centos ~]# vim install_nginx.yml
写法一:
---
- name: 这是一个安装nginx的剧本 【剧本的名称】
hosts: web 【hosts表示主机组或者某台主机ip都可以】
tasks: 【task表示任务列表,开始键,不需要 `-`,因为它是一个字典中的项。】
- name: 01 安装nginx【这是任务列表中的第一个任务,使用 `-` 表示它是一个列表项。】
yum: 【采用的模块,对应-m】
name: nginx 【执行模块的动作参数,对应-a】
state: installed
- name: 02 启动nginx
systemd:
name: nginx
state: started
写法二:
yum: name=nginx state=installed
systemd: name=nginx state=started
四、命令执行
1、执行命令结果【状态颜色】
绿色:命令以用户期望的执行了,但是状态没有发生改变;
黄色:命令以用户期望的执行了,并且状态发生了改变;
紫色:警告信息,说明ansible提示你有更合适的用法;
红色:命令错误,执行失败;
蓝色:详细的执行过程。
2、与shell比较:
shell脚本效率较低,且不做状态记录;
ansible则会返回执行状态,且可以观察到不同的执行结果状态,避免重复执行。
五、常用模块
查找模块:ansible-doc -l | grep ^(匹配) 得到模块名
查找使用方式:ansible-doc -s 模块名
1、ping模块
语法:ansible 主机组 -m 模块名 [模块参数]
作用:通过管理机查看目标机器是否运行
示例:ansible all -m ping
2、command简单命令模块
语法:ansible-doc -s command 查看信息
命令:ansible 主机组 -m command -a "需要批量执行的命令"
只支持简单命令执行,普通的linux命令等;command模块是ansible命令基本模块
使用command模块执行远程命令,命令不得用变量($HOME)
不得出现特殊符号,否则无法识别,需要用shell模块实现,即无法实现复杂的linux命令
示例:ansible web -m command -a "hostname"
包括:远程查看主机内存free -m;远程创建文件、查看文件touch、cat等;远程获取机器负载uptime;uptime 是 Linux 系统中用于查看系统运行时间、当前负载和登录用户信息的命令。
关闭告警信息:warn=false
选项参数:
a】chdir:在执行命令执行时,通过cd命令进入指定目录
ansible web -m command -a "tar -zcvf /opt/log.tgz /var/log chdir=/"
b】removes:定义一个文件是否存在,如果存在则运行相应命令;如果不存在则跳过;
ansible web -a "tar -zcf /backup-config/etc.tgz etc chdir=/ removes=/back-config"【由于backup-config本身就还不存在,所以需要用removes】
c】远程过滤进程信息,无法使用,因为command不支持特殊符号,此时需要指定模块shell;虽然ansible提供了大量的模块,但是shell可以作为万能模块执行多种复杂的命令
3、shell模块
等于在linux上直接执行任何复杂的命令,但是ansible的使用理念是,在使用shell模块之前,先查一下是否有对应的模块;
ansible all -m shell -a "ps -ef | grep ssh"
如:ansible web -m shell -a "mkdir /0224/;echo 'hostname' > /0224/hostname.sh;chmod +x /0224/hostname.sh; /0224/hostname.sh; warn=false"
4、copy模块:拷贝文件
远程推送数据模块,只能把数据推送给远程主机节点,无法拉取到本机
关键参数:
a】src 指定本机源文件路径;
b】dest:指定目标机器存放路径(必须)
例如:ansible web -m copy -a "src=/root/happy.txt dest=/root/shell_test"
其他参数:
c】group:指定目标组;
d】user:指定目标用户;
e】mod:指定权限
f】backup:防止覆盖远程文件,丢失备份,提前备份该目标主机的数据,backup=yes
例如:ansible web -m copy -a "src=/root/happy.txt dest=/root/shell_test/happy.txt backup=yes"
g】content参数:向dest写入内容,并且覆盖其原有的文件内容
【注意:拷贝文件或者文件夹一定要注意结尾是否携带斜杠 "src=/root/" 和 "src=/root"是不一样的】
5、file模块:
主要用于创建文件、目录数据,以及对现有的文件、目录权限进行修改,对文件属性操作;
a】远程创建文件:
例如:ansible web -m file -a "path=/root/shell-test/happy.txt state=touch"
b】远程创建文件夹:【主要看path 和 state参数】
例如:ansible web -m file -a "path=/root/shell-test/happy state=directory"
c】创建文件且设定权限【path、state、owner、group】
例如:ansible web -m file -a "path=/root/shell-test/happy.txt state=touch owner=www group=www"
d】远程修改文件属性【mode】
例如:ansible web -m file -a "path=/root/shell-test/happy.txt state=touch owner=www group=www mode=777"
e】远程进行软连接【state=link】
例如:ansible web -m file -a "src=/etc/hosts dest=/opt/hosts state=link"
f】强制创建软连接【+ force=yes】
6、script脚本模块:传输后在远程节点上运行本地脚本
(1)把脚本发到目标机器上执行;
(2)远程执行,目标机器上不需要存在这个脚本;
a】create:定义一个文件是否存在,若不存在,则运行相应命令,存在则跳过
b】free-from:参数信息中可以输入任何系统命令、实现远程管理
c】removes:定义一个文件是否存在,如果存在,则运行相应命令,存在则跳过
【先创建脚本-》添加权限-》远程执行-》检查结果】
例如:ansible web -m script -a "/root/shell-test/while.sh"
增加-v选项或者-vvvv选项,表示显示详细运行过程;
7、cron定时任务模块:
1、用于管理定时任务的记录,编写任务
对比ansible的cron模块,和crontab:常见的参数,适用ansible编写定时任务,和直接编写是没有什么区别的;
ansible中,相关参数为:minute、hour、day、month、weekday、special-time
例如:ansible web -m cron -a "name='ntp aliyun' minute=*/5 job='ntpdate -u ntp.aliyun.com'"
结果:
[root@centoscopy1 shell_test]# crontab -l
#Ansible: ntp aliyun
*/5 * * * * ntpdate -u ntp.aliyun.com
a】name参数:设置计划任务的名称,会在注释中显示;
b】job参数:指定计划的任务中需要实际执行的命令或者脚本;
c】backup参数:修改或删除计划任务时,会先对假话任务进行备份;backup=yes;
d】state=absent:表示删除计划或者任务;
例如:ansible web -m cron -a "name='None' state=absent"
2、修改指定名称的定时任务:
例如:将原有的计划修改为每晚11点半
ansible web -m cron -a "name = 'ntp aliyun' minute=30 hour=23 job='ntpdate -u ntp.aliyun.com'"
8、group模块:
管理系统用户组的模块,【就是对租进行管理,包括创建、删除、查看】
参数:
a】name:创建指定的组名
b】gid:组的GID
c】state :absent移除远程主机的组、present创建组
创建:ansible web -m group -a "name=user1 gid=1234 "
删除:ansible web -m group -a "name=user1 gid=1234 state=absent"
查看:cat /etc/group
9、user用户模块:
用户管理:关于用户:uid、用户名、用户主组、用户附加组、创建用户、删除用户、创建用户公私钥、用户密码过期时间等
示例:ansible web -m user -a "name=user1 uid=1111"
10、yum模块:专用于管理软件的模块
参数:
a】卸载:state=absent
b】安装:state=installed
c】升级:state=latest
示例:卸载rsync服务
ansible web -m yum -a "name=rsync state=absent"
【其中name表示管理软件的名字】
11、systemd模块:针对yum包管理,功能同systemctl
参数:
a】state:started、stopped、restarted、reloaded
b】name:服务名称
c】enabled=yes \ no 表示开启|关闭自启动
示例:设置nginx自启动
ansible web -m systemd -a "name=nginx state=started enabled=yes"
12、archive压缩模块
支持压缩类型:bz2、tar、gz(default)、xz、zip 参数:指定压缩方向由path->dest和format即可
参数:
a】path:被压缩路径
b】dest:压缩到目标文件
c】format:指定压缩类型
示例:path=/etc dest=/tmp/all-etc.tar.gz
ansible web -m archive -a "path=/etc dest=/tmp/etc-all.tar.gz "
若要压缩为zip文件:
ansible web -m archive -a "path=/etc dest=/tmp/etc-all.tar.gz format=zip"
14、unarchive解压缩模块
示例:ansible web -m unarchive -a "src=/opt/etc.tgz dest=/tmp/"
解压缩src压缩包到dest 【a情况】
分两种情况:
a】管理机的压缩文件,解压到目标机器的目录
b】目标机器的压缩文件,解压到目标机器本地 【增加参数 remote-src=yes】
15、setup模块:ansible默认提供的模块
管理机在通过ssh远程连接,操作目标机器的时候,ansible会默认收集这个机器的所有信息,放入到一个setup模块中,这个机器的主机名,ip地址,mac地址,磁盘数量,是否虚拟化,时间、cpu核数都会存放到setup模块中【会默认采集目标机器的所有静态信息,返回的数据类型是json,可以通过jq去提取目标机器的属性】
语法:ansible web -m setup
16、debug模块:打印变量
语法:"{{ 自定义变量名 }}" 【vars关键字提供】、"{{ 内置变量名 }}" 【setup模块提供】
六、剧本playbook
主要就是两部分:ansible模块(模块的参数) 以及 yaml语法。
yaml是将多个临时命令的语句转变为剧本的一种写法,其特点有:
1)严格的缩进(空格数)表示层级关系(一般敲2个空格表示一个层级关系);
2)不要使用tab键;
3)冒号:后面一定得有空格;
4)短横线- 后面一定得有空格;
5)剧本文件名必须是yaml或者yml,程序可以读取,以及vim提供颜色高亮;
编写示例:
1)vim install-nginx.yml 【必须是yml结尾或者yaml】
2)[root@centos ~]# cat install_nginx.yml 【严格的层级关系,不同层,一定要用两个空格隔开】
写法1:
---
- name: 这是一个安装nginx的剧本 【剧本的名称】
hosts: web 【hosts表示主机组或者某台主机ip都可以】
tasks: 【task表示任务列表,开始键,不需要 `-`,因为它是一个字典中的项。】
- name: 01 安装nginx 【这是任务列表中的第一个任务,使用 `-` 表示它是一个列表项。】
yum:
name: nginx
state: installed
- name: 02 启动nginx
systemd:
name: nginx
state: started
写法2:
---
- name: 这是一个安装nginx的剧本
hosts: web
tasks:
- name: 01 安装nginx
yum: name=nginx state=installed 【用的是等号】
- name: 02 启动nginx
systemd: name=nginx state=started
- name: 03 设置nginx开机自启
systemd: name=nginx enabled=yes
补充:
1)yaml语法中只有三个数据类型:
a】字典类型:key:value , 且后面必须有个空格;
b】列表形式:通过短横线定义 ,一个【-】就表示一个新的列表;
【shell中也支持列表,表现形式为:students=("x" "y" "z")类似的】
c】纯变量形式:
【短横线用于定义列表:
多个短横线,同一个缩进下的元素,表示一个列表中的多个元素
一个短横线,同一个缩进下的元素,表示是一个整体,大字符串】
2)json语法(网站数据传输,数据传输最主流的格式):
根据key,提取value,运维通过jq命令提取
[root@centos ~]# echo '{"name":"cc","say":"hello"}' 【不用jq】
{"name":"cc","say":"hello"}
[root@centos ~]# echo '{"name":"cc","say":"hello"}' | jq 【使用jq】
{
"name": "cc",
"say":"hello"
}
jq语法:通过【.】提取,比如jq '.name,.say'
[root@centos ~]# echo '{"name":"cc","say":"hello"}' | jq '.name,.say'
"cc"
"say":"hello"
[root@centos ~]# echo '{"name":[{"weight":120,"age":20},{"high":"170","age":22}],"say":"hello"}' | jq '.name | .[0] | .age' 【取复合字典中的对应元素】
结果:20
七、高级属性与role角色
1、循环loop
a)直接使用:
- name: create user test1~3
hosts: backup
tasks:
- name: create test1-3 【循环创建用户】
user:
name: "{{item}}"
state: present
loop:
- test1
- test2
- test3
- name: set password
shell: echo 'xxxx' | passwd --stdin "{{item}}" 【循环设置密码】
loop:
- test1
- test2
- test3
b)基于{{item}}和vars使用:
---
- name: create user
hosts: web
vars:
users-info:
- {user: 'test1', password: '0001'} 或 - test1
- {user: 'test2', password: '0002'} test2
- {user: 'test3', password: '0003'} test3
tasks:
- name: create user
user:
name:
"{{ item.user }}" 【注意:loop依旧是users-info,但是要取不同的元素,在item.xxx中取】
state: present
loop:
"{{ users-info }}"
- name: set password
shell: echo 'cc666' | passwd --stdin "{{ item.password }}"
loop: "{{ users-info }}"
1)loop关键字用于对某变量进行循环提取,指定循环变量名,写法:【loop: "{{ user-info(变量名) }}"】
2)item负责在变量中取值,写法:"{{ item }}";除此之外,还有获取值的语法是"{{变量名}}"例如:
data-path:xxx
dest-path:xxx
config-path:xxx
在后续的使用脚本时,可以直接更改变量,而不用动内部信息,方便复用
3)vars定义全局变量,提供循环内容;
【使用场景】:创建多个用户、安装多个软件、创建多个文件夹、复制多个目录、设置文件权限等;
【变量定义使用包括】:应用场景、vars自定义变量、获取主机静态属性(ip地址)、完整的ansible内置变量手册、主机清单文件中也用到了变量、loop循环中引用变量;
【内置变量】:setup模块采集的静态属性,可以通过过滤器语法提取;
变量vars总结:
1】vars自定义变量,结合loop使用;
2】ansible内置变量:setup采集的静态属性都可以作为内置变量,可以通过过滤器语法提取;
---
- name: 获取对接主机信息
hosts: web
tasks:
- name: 获取ip地址
debug:
msg: "ip地址是{{ ansible-all-ipv4-addresses }}"
- name: 获取主机名
debug:
msg: "hostname是 {{ ansible-hostname }}"
- name: 单ip
debug:
msg: "单ip是 {{ ansible-default-ipv4.address }}"
- name: eth0 ip地址
debug:
msg: "etho的ip地址是 {{ ansible-facts.ens33.ipv4.address }}"
3】主机清单中的变量 /etc/ansible/hosts;
4】注册变量:register提供;ansible的模块在运行之后,其实都会返回一些返回值,只是默认情况下这些返回值并不会显示而已,register可以将这个返回值注册到一个变量中,打印这个变量的值就可以看到返回值信息了。
2、重启服务register + when
---
- hosts: all
become: false
tasks:
- name: 【检查文件是否存在】
stat:
path: /tmp/cc_file.txt
register: cc_check 【将stat模块的执行结果注册到变量 file_check】
- name: 【如果实际文件不存在】
file:
path: /tmp/cc_file.txt
state: touch 【创建文件并刷新时间戳,等同于 touch 命令】
mode: 0664
when: not cc_check.stat.exists 【当文件不存在时,才执行该任务】
1)register+when是针对tasks任务列表下,某一个任务设置的:
作用分别是:
1、获取某任务的命令执行结果(返回值);
2、利用when条件判断,针对返回值的不同状态(决定做什么事);
2)when: file-status.changed :表示能够得到ture或false的状态
当为true的时候,就表示这个配置文件是发送了修改,因此需要调用这个任务;
以及: is success 和 is failed,分别表示在返回值执行成功或者失败时要执行的任务。
3、触发器handlers + notify
---
- name: ynchaoit.cn
hosts: web
remote_user: root
tasks:
- name: copy rsyncd.conf
copy:
src=/etc/rsyncd.conf
dest=/etc/
notify: 【当某一个任务执行,发生了change更改状态,就会触发notify的执行】
- restart rsyncd.service
handlers:
- name: restart rsyncd.service
systemd:
name: rsyncd
state: restarted
特性:和tasks平级,必须写在剧本的最后面,可以定义多个要执行的事件
作用:定义事件名字以及动作,例如:systemd 重启rsync服务,再notify去调用这个handlers事件;判断前面的模块任务执行是否是change的状态,如果是,则用notify指定的handler去运行 【和register+when类似】。
4、标签tag
---
- name: ccyw.nginx
hosts: web_servers
tasks:
- name: 01 安装Nginx
yum: name=nginx state=installed
tags: 01_install_software
- name: 02 启动Nginx服务
service: name=nginx state=started enabled=yes
tags: 02_service_management
- name: 03 配置Nginx
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: 03_config_setup
- name: 04 创建web目录
file: path=/var/www/html owner=nginx group=nginx state=directory
tags: 04_directory_setup
对任务进行“打标签”,当任务存在标签以后,我们就可以在执行playbook时,借助标签,指定执行哪些任务,或者指定不执行哪些任务;
作用:调试、选择性的执行某个task
使用:
1)--list-tags:列出所有可用标签 ansible-playbook --list-tags install_nfs.yaml;
2)--skip-tags SKIP_TAGS:只运行没匹配的标签,即跳过匹配的标签 ansible-playbook --skip-tags 05_create_data_dir;
3)-t TAGS, --tags TAGS:只运行匹配的标签;
tasks:
1)--list-tasks:列出所有任务和对应标签;
2)--start-at-task START-AT-TASK:指定从哪个tasks开始运行;
例如:ansible-playbook --start-at-task "03_config_setup" install_nginx.yaml ;
即:从第3个任务开始执行,包括后面的任务。
5、role角色
1)角色允许基于已知的文件结构自动加载相关的变量、文件、任务、处理程序和其他ansible工作,将内容按照role角色分组后,可以轻松地重复使用他们并与其他用户共享他们【结构化、层次化组织多个playbook】。
2)功能:定义一堆规范,让写剧本有规章制度;
优势:把单个大剧本,拆分为小剧本,便于维护、修改和使用,完成解耦、结构更清晰、调试更方便;
如果是小部署,还是剧本更方便。
3)role的用法:
role主要依赖于目录的命名和摆放,默认tasks/main.yml是所有任务的入口,使用roles的过程也可以认为是目录规范化命名的过程,而每个目录下均由main.yml定义该功能的任务集,tasks/main.yml默认执行所有定义的任务。
4)步骤:
第一步:定义好role的存放路径:roles_path = /etc/ansible/roles;
第二步:创建role的固定目录:
site.yml # role入口
nfs-servers.yml # role
rsync-servers.yml # role
roles/ # role规范目录结构
nfs-servers/ # role具体名字
tasks/ # 剧本任务
handlers/ # 剧本里存放的handlers
files/ # 如压缩文件,如需要拷贝的文件
templates/ # 存放配置文件
vars/ # 存放变量文件
rsync-servers/
tasks/
handlers/
files/
templates/
第三步:创建如上的目录结构:
mkdir -p /etc/ansible/roles # 这里的文件名,必须和roles目录下的每一个任务目录同名
touch /etc/ansible/{site.yml,nfs-servers.yml,rsync-servers.yml}
第四步:创建关于rsync-servers的目录:
mkdir -p /etc/ansible/roles/rsync-servers/{tasks,handlers,files,templates,vars}
第五步:检查创建好的目录结构:
[root@centos ansible]# tree /etc/ansible
/etc/ansible
├── ansible.cfg
├── hosts
├── nfs-servers.yml
├── roles
│ └── rsync-servers 【有其他的剧本,可以写入,与此平级;对于原本的剧本,将内容拆分为下面的几个目录,依次配置文件】
│ ├── files
│ ├── handlers
│ ├── tasks
│ ├── templates 【没用到的目录,空着即可】
│ └── vars
├── rsync-servers.yml
└── site.yml
第六步:部署rsync服务的role角色
1)写好playbook模式
2)拆开即可
示例:
安装rsync的启动文件rsync-servers.yml:【要和roles平级,指定hosts和启动角色文件rsync-servers】
- hosts:web
roles:
- rsync-servers 【定义安装rsync这个角色的工作目录,在roles/rsync-servers的文件夹】
在handlers目录下创建main.yml:【去除头部】
- name:restart-rsyncd
systemd:
name:rsyncd
state:restarted
在vars目录下创建main.yml:【无需头部和缩进,直接存放定义的变量,但是要和tasks中对应】
user-id: '8888'
rsync-user: 'www'
补充:分别在什么情况下用到files和templates:
1)用 files/:当文件内容完全固定且无需环境适配时(如 redis.conf、init.d 脚本)。
2)用 templates/:当文件需要动态生成时(如根据 {{ ansible_os_family }} 写入不同 OS 的配置片段,或用 {{ port }} 替换端口)。
5060

被折叠的 条评论
为什么被折叠?



