可以从ansible-doc -l | grep来找出想要的模块。再使用ansible-doc -s module_name来查看此模块的用法。官方模块列表和说明:https://docs.ansible.com/ansible/latest/modules_by_category.html
关于模块的使用方法,需要注意的是"state"。很多模块都会有该选项,且其值几乎都包含有"present"和"absent",表示肯定和否定的意思。
ansible绝大多数模块都天然具有幂等
特性,只有极少数模块如shell和command模块不具备幂等性。所谓的幂等性是指多次执行同一个操作不会影响最终结果。例如,ansible的yum模块安装rpm包时,如果待安装的包已经安装过了,则再次或多次执行安装操作都不会真正的执行下去。再例如,copy模块拷贝文件时,如果目标主机上已经有了完全相同的文件,则多次执行copy模块不会真正的拷贝。ansible具有幂等性的模块在执行时,都会自动判断是否要执行。
2.1 主机连通性测试
我们使用ansible web -m ping
命令来进行主机连通性测试,效果如下:
[root@server ~]# ansible web -m ping
192.168.37.122 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.37.133 | SUCCESS => {
"changed": false,
"ping": "pong"
}
这样就说明我们的主机是连通状态的。接下来的操作才可以正常进行。
2.2 command 模块
这个模块可以直接在远程主机上执行命令,并将结果返回本主机。
举例如下:
[root@gxw-server3 ~]# ansible web -m command -a "ss -ntl"
10.0.0.27 | CHANGED | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:111 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::111 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
10.0.0.28 | CHANGED | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:111 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::111 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 ::
使用(shell)模块实现这些功能)。注意,该命令不支持| 管道命令
。
下面来看一看该模块下常用的几个命令:
chdir # 在执行命令之前,先切换到该目录
executable # 切换shell来执行命令,需要使用命令的绝对路径
free_form # 要执行的Linux指令,一般使用Ansible的-a参数代替。
creates # 一个文件名,当这个文件存在,则该命令不执行,可以用来做判断
removes # 一个文件名,这个文件不存在,则该命令不执行
下面我们来看看这些命令的执行效果:
[root@gxw-server3 ~]# ansible web -m command -a 'chdir=/data/ ls' #先切换到/data 目录 在执行ls
10.0.0.27 | CHANGED | rc=0 >>
1.txt
2.txt
3.txt
10.0.0.28 | CHANGED | rc=0 >>
1.txt
2.txt
3.txt
[root@gxw-server3 ~]# ansible web -m command -a 'creates=/data/1.jpg ls' #如果/data/1.jpg 不存在,执行ls;若/data/1.jpg存在,则不执行
10.0.0.28 | CHANGED | rc=0 >>
original-ks.cfg
10.0.0.27 | CHANGED | rc=0 >>
original-ks.cfg
[root@gxw-server3 ~]# ansible web -m command -a 'removes=/data/1.jpg ls' #如果/data/1.jpg不存在, 不执行ls
10.0.0.28 | SUCCESS | rc=0 >>
skipped, since /data/1.jpg does not exist
10.0.0.27 | SUCCESS | rc=0 >>
skipped, since /data/1.jpg does not exist
[root@gxw-server3 ~]# ansible web -m command -a 'removes=/data/1.txt ls' #若/data/1.txt存在,执行ls
10.0.0.27 | CHANGED | rc=0 >>
original-ks.cfg
10.0.0.28 | CHANGED | rc=0 >>
original-ks.cfg
2.3 shell 模块
shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。
[root@gxw-server3 ~]# ansible web -m shell -a 'cat /etc/passwd | tail -1 '
10.0.0.28 | CHANGED | rc=0 >>
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
10.0.0.27 | CHANGED | rc=0 >>
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
只要是我们的shell命令,都可以通过这个模块在远程主机上运行,这里就不一一举例了。
2.4 copy 模块
这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。
其相关选项如下:
src
#被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于"rsync"content
#用于替换"src",可以直接指定文件的值dest
#必选项,将源文件复制到的远程主机的绝对路径backup
#当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息directory_mode
#递归设定目录的权限,默认为系统默认权限force
#当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;设为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes"others
#所有的 file 模块中的选项可以在这里使用
用法举例如下:
① 复制文件:
[root@server ~]# ansible web -m copy -a 'src=~/hello dest=/data/hello'
192.168.37.122 | SUCCESS => {
"changed": true,
"checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"dest": "/data/hello",
"gid": 0,
"group": "root",
"md5sum": "6f5902ac237024bdd0c176cb93063dc4",
"mode": "0644",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512437093.55-228281064292921/source",
"state": "file",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"changed": true,
"checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"dest": "/data/hello",
"gid": 0,
"group": "root",
"md5sum": "6f5902ac237024bdd0c176cb93063dc4",
"mode": "0644",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512437093.74-44694985235189/source",
"state": "file",
"uid": 0
}
② 给定内容生成文件,并制定权限
[root@server ~]# ansible web -m copy -a 'content="I am keer\n" dest=/data/name mode=666'
192.168.37.122 | SUCCESS => {
"changed": true,
"checksum": "0421570938940ea784f9d8598dab87f07685b968",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "497fa8386590a5fc89090725b07f175c",
"mode": "0666",
"owner": "root",
"size": 10,
"src": "/root/.ansible/tmp/ansible-tmp-1512437327.37-199512601767687/source",
"state": "file",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"changed": true,
"checksum": "0421570938940ea784f9d8598dab87f07685b968",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "497fa8386590a5fc89090725b07f175c",
"mode": "0666",
"owner": "root",
"size": 10,
"src": "/root/.ansible/tmp/ansible-tmp-1512437327.55-218104039503110/source",
"state": "file",
"uid": 0
}
我们现在可以去查看一下我们生成的文件及其权限:
[root@server ~]# ansible web -m shell -a 'ls -l /data/'
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-rw-rw- 1 root root 12 Dec 6 09:45 name
192.168.37.133 | SUCCESS | rc=0 >>
total 40
-rw-rw-rw- 1 root root 12 Dec 5 09:45 name
可以看出我们的name文件已经生成,并且权限为666。
③ 关于覆盖
我们把文件的内容修改一下,然后选择覆盖备份:
[root@server ~]# ansible web -m copy -a 'content="I am keerya\n" backup=yes dest=/data/name mode=666'
192.168.37.122 | SUCCESS => {
"backup_file": "/data/name.4394.2017-12-06@09:46:25~",
"changed": true,
"checksum": "064a68908ab9971ee85dbc08ea038387598e3778",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "8ca7c11385856155af52e560f608891c",
"mode": "0666",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512438383.78-228128616784888/source",
"state": "file",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"backup_file": "/data/name.5962.2017-12-05@09:46:24~",
"changed": true,
"checksum": "064a68908ab9971ee85dbc08ea038387598e3778",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "8ca7c11385856155af52e560f608891c",
"mode": "0666",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512438384.0-170718946740009/source",
"state": "file",
"uid": 0
}
现在我们可以去查看一下:
[root@server ~]# ansible web -m shell -a 'ls -l /data/'
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-rw-rw- 1 root root 12 Dec 6 09:46 name
-rw-rw-rw- 1 root root 10 Dec 6 09:45 name.4394.2017-12-06@09:46:25~
192.168.37.133 | SUCCESS | rc=0 >>
total 40
-rw-rw-rw- 1 root root 12 Dec 5 09:46 name
-rw-rw-rw- 1 root root 10 Dec 5 09:45 name.5962.2017-12-05@09:46:24~
可以看出,我们的源文件已经被备份,我们还可以查看一下name
文件的内容:
[root@server ~]# ansible web -m shell -a 'cat /data/name'
192.168.37.122 | SUCCESS | rc=0 >>
I am keerya
192.168.37.133 | SUCCESS | rc=0 >>
I am keerya
证明,这正是我们新导入的文件的内容。
2.5 file 模块
该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。
下面是一些常见的命令:
force
#需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|nogroup
#定义文件/目录的属组。后面可以加上mode
:定义文件/目录的权限owner
#定义文件/目录的属主。后面必须跟上path
:定义文件/目录的路径recurse
#递归设置文件的属性,只对目录有效,后面跟上src
:被链接的源文件路径,只应用于state=link
的情况dest
#被链接到的路径,只应用于state=link
的情况state
#状态,有以下选项:
directory
:如果目录不存在,就创建目录file
:即使文件不存在,也不会被创建link
:创建软链接hard
:创建硬链接touch
:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间absent
:删除目录、文件或者取消链接文件
用法举例如下:
① 创建目录:
[root@server ~]# ansible web -m file -a 'path=/data/app state=directory'
192.168.37.122 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/app",
"size": 6,
"state": "directory",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/app",
"size": 4096,
"state": "directory",
"uid": 0
}
我们可以查看一下:
[root@server ~]# ansible web -m shell -a 'ls -l /data'
192.168.37.122 | SUCCESS | rc=0 >>
total 28
drwxr-xr-x 2 root root 6 Dec 6 10:21 app
192.168.37.133 | SUCCESS | rc=0 >>
total 44
drwxr-xr-x 2 root root 4096 Dec 5 10:21 app
可以看出,我们的目录已经创建完成。
② 创建链接文件
[root@server ~]# ansible web -m file -a 'path=/data/bbb.jpg src=aaa.jpg state=link'
192.168.37.122 | SUCCESS => {
"changed": true,
"dest": "/data/bbb.jpg",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 7,
"src": "aaa.jpg",
"state": "link",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"changed": true,
"dest": "/data/bbb.jpg",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 7,
"src": "aaa.jpg",
"state": "link",
"uid": 0
}
我们可以去查看一下:
[root@server ~]# ansible web -m shell -a 'ls -l /data'
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-r--r-- 1 root root 5649 Dec 5 13:49 aaa.jpg
lrwxrwxrwx 1 root root 7 Dec 6 10:25 bbb.jpg -> aaa.jpg
192.168.37.133 | SUCCESS | rc=0 >>
total 44
-rw-r--r-- 1 root root 5649 Dec 4 14:44 aaa.jpg
lrwxrwxrwx 1 root root 7 Dec 5 10:25 bbb.jpg -> aaa.jpg
我们的链接文件已经创建成功。
③ 删除文件
[root@server ~]# ansible web -m file -a 'path=/data/a state=absent'
192.168.37.122 | SUCCESS => {
"changed": true,
"path": "/data/a",
"state": "absent"
}
192.168.37.133 | SUCCESS => {
"changed": true,
"path": "/data/a",
"state": "absent"
}
我们可以查看一下:
[root@server ~]# ansible web -m shell -a 'ls /data/a'
192.168.37.122 | FAILED | rc=2 >>
ls: cannot access /data/a: No such file or directory
192.168.37.133 | FAILED | rc=2 >>
ls: cannot access /data/a: No such file or directory
发现已经没有这个文件了。
2.6 fetch 模块
该模块用于从远程某主机获取(复制)文件到本地。
有两个选项:
dest
:用来存放文件的目录src
:在远程拉取的文件,并且必须是一个file,不能是目录
具体举例如下:
[root@server ~]# ansible web -m fetch -a 'src=/data/hello dest=/data'
192.168.37.122 | SUCCESS => {
"changed": true,
"checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"dest": "/data/192.168.37.122/data/hello",
"md5sum": "6f5902ac237024bdd0c176cb93063dc4",
"remote_checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"remote_md5sum": null
}
192.168.37.133 | SUCCESS => {
"changed": true,
"checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"dest": "/data/192.168.37.133/data/hello",
"md5sum": "6f5902ac237024bdd0c176cb93063dc4",
"remote_checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"remote_md5sum": null
}
我们可以在本机上查看一下文件是否复制成功。要注意,文件保存的路径是我们设置的接收目录下的被管制主机ip
目录下:
[root@server ~]# cd /data/
[root@server data]# ls
1 192.168.37.122 192.168.37.133 fastdfs web
[root@server data]# cd 192.168.37.122
[root@server 192.168.37.122]# ls
data
[root@server 192.168.37.122]# cd data/
[root@server data]# ls
hello
[root@server data]# pwd
/data/192.168.37.122/data
2.7 cron 模块
该模块适用于管理cron
计划任务的。
其使用的语法跟我们的crontab
文件中的语法一致,同时,可以指定以下选项:
day=
#日应该运行的工作( 1-31, , /2, )hour=
# 小时 ( 0-23, , /2, )minute=
#分钟( 0-59, , /2, )month=
# 月( 1-12, *, /2, )weekday=
# 周 ( 0-6 for Sunday-Saturday,, )job=
#指明运行的命令是什么name=
#定时任务描述reboot
# 任务在重启时运行,不建议使用,建议使用special_timespecial_time
#特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)state
#指定状态,present表示添加定时任务,也是默认设置,absent表示删除定时任务user
# 以哪个用户的身份执行
举例如下:
① 添加计划任务
[root@server ~]# ansible web -m cron -a 'name="ntp update every 5 min" minute=*/5 job="/sbin/ntpdate 172.17.0.1 &> /dev/null"'
192.168.37.122 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"ntp update every 5 min"
]
}
192.168.37.133 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"ntp update every 5 min"
]
}
我们可以去查看一下:
[root@server ~]# ansible web -m shell -a 'crontab -l'
192.168.37.122 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
192.168.37.133 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
可以看出,我们的计划任务已经设置成功了。
② 删除计划任务
如果我们的计划任务添加错误,想要删除的话,则执行以下操作:
首先我们查看一下现有的计划任务:
[root@server ~]# ansible web -m shell -a 'crontab -l'
192.168.37.122 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
#Ansible: df everyday
* 15 * * * df -lh >> /tmp/disk_total &> /dev/null
192.168.37.133 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
#Ansible: df everyday
* 15 * * * df -lh >> /tmp/disk_total &> /dev/null
然后执行删除操作:
[root@server ~]# ansible web -m cron -a 'name="df everyday" hour=15 job="df -lh >> /tmp/disk_total &> /dev/null" state=absent'
192.168.37.122 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"ntp update every 5 min"
]
}
192.168.37.133 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"ntp update every 5 min"
]
}
删除完成后,我们再查看一下现有的计划任务确认一下:
[root@server ~]# ansible web -m shell -a 'crontab -l'
192.168.37.122 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
192.168.37.133 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
我们的删除操作已经成功。
2.8 yum 模块
顾名思义,该模块主要用于软件的安装。
其选项如下:
name=
#所安装的包的名称state=
#present
--->安装,latest
--->安装最新的,absent
---> 卸载软件。update_cache
#强制更新yum的缓存conf_file
#指定远程yum安装时所依赖的配置文件(安装本地已有的包)。disable_pgp_check
#是否禁止GPG checking,只用于present
orlatest
。disablerepo
#临时禁止使用yum库。 只用于安装或更新时。enablerepo
#临时使用的yum库。只用于安装或更新时。
下面我们就来安装一个包试试看:
[root@server ~]# ansible web -m yum -a 'name=htop state=present'
192.168.37.122 | SUCCESS => {
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package htop.x86_64 0:2.0.2-1.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n htop x86_64 2.0.2-1.el7 epel 98 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 98 k\nInstalled size: 207 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : htop-2.0.2-1.el7.x86_64 1/1 \n Verifying : htop-2.0.2-1.el7.x86_64 1/1 \n\nInstalled:\n htop.x86_64 0:2.0.2-1.el7 \n\nComplete!\n"
]
}
192.168.37.133 | SUCCESS => {
"changed": true,
"msg": "Warning: RPMDB altered outside of yum.\n** Found 3 pre-existing rpmdb problem(s), 'yum check' output follows:\nipa-client-4.4.0-12.el7.centos.x86_64 has installed conflicts freeipa-client: ipa-client-4.4.0-12.el7.centos.x86_64\nipa-client-common-4.4.0-12.el7.centos.noarch has installed conflicts freeipa-client-common: ipa-client-common-4.4.0-12.el7.centos.noarch\nipa-common-4.4.0-12.el7.centos.noarch has installed conflicts freeipa-common: ipa-common-4.4.0-12.el7.centos.noarch\n",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package htop.x86_64 0:2.0.2-1.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n htop x86_64 2.0.2-1.el7 epel 98 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 98 k\nInstalled size: 207 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : htop-2.0.2-1.el7.x86_64 1/1 \n Verifying : htop-2.0.2-1.el7.x86_64 1/1 \n\nInstalled:\n htop.x86_64 0:2.0.2-1.el7 \n\nComplete!\n"
]
}
安装成功。
2.9 service 模块
该模块用于服务程序的管理。
其主要选项如下:
arguments
#命令行提供额外的参数enabled
#设置开机启动。name=
#服务名称runlevel
#开机启动的级别,一般不用指定。sleep
#在重启服务的过程中,是否等待。如在服务关闭以后等待2秒再启动。(定义在剧本中。)state
#有四种状态,分别为:started
--->启动服务,stopped
--->停止服务,restarted
--->重启服务,reloaded
--->重载配置
下面是一些例子:
① 开启服务并设置自启动
[root@server ~]# ansible web -m service -a 'name=nginx state=started enabled=true'
192.168.37.122 | SUCCESS => {
"changed": true,
"enabled": true,
"name": "nginx",
"state": "started",
……
}
192.168.37.133 | SUCCESS => {
"changed": true,
"enabled": true,
"name": "nginx",
"state": "started",
……
}
我们可以去查看一下端口是否打开:
[root@server ~]# ansible web -m shell -a 'ss -ntl'
192.168.37.122 | SUCCESS | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
192.168.37.133 | SUCCESS | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
可以看出我们的80端口已经打开。
② 关闭服务
我们也可以通过该模块来关闭我们的服务:
[root@server ~]# ansible web -m service -a 'name=nginx state=stopped'
192.168.37.122 | SUCCESS => {
"changed": true,
"name": "nginx",
"state": "stopped",
……
}
192.168.37.133 | SUCCESS => {
"changed": true,
"name": "nginx",
"state": "stopped",
……
}
一样的,我们来查看一下端口:
[root@server ~]# ansible web -m shell -a 'ss -ntl | grep 80'
192.168.37.122 | FAILED | rc=1 >>
192.168.37.133 | FAILED | rc=1 >>
可以看出,我们已经没有80端口了,说明我们的nginx服务已经关闭了。
2.10 user 模块
该模块主要是用来管理用户账号。
其主要选项如下:
comment
# 用户的描述信息createhome
# 是否创建家目录force
# 在使用state=absent时, 行为与userdel –force一致.group
# 指定基本组groups
# 指定附加组,如果指定为(groups=)表示删除所有组home
# 指定用户家目录move_home
# 如果设置为home=时, 试图将用户主目录移动到指定的目录name
# 指定用户名non_unique
# 该选项允许改变非唯一的用户ID值password
# 指定用户密码remove
# 在使用state=absent时, 行为是与userdel –remove一致shell
# 指定默认shellstate
# 设置帐号状态,不指定为创建,指定值为absent表示删除system
# 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户uid
# 指定用户的uid
举例如下:
① 添加一个用户并指定其 uid
[root@server ~]# ansible web -m user -a 'name=keer uid=11111'
192.168.37.122 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 11111,
"home": "/home/keer",
"name": "keer",
"shell": "/bin/bash",
"state": "present",
"stderr": "useradd: warning: the home directory already exists.\nNot copying any file from skel directory into it.\nCreating mailbox file: File exists\n",
"system": false,
"uid": 11111
}
192.168.37.133 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 11111,
"home": "/home/keer",
"name": "keer",
"shell": "/bin/bash",
"state": "present",
"stderr": "useradd: warning: the home directory already exists.\nNot copying any file from skel directory into it.\nCreating mailbox file: File exists\n",
"system": false,
"uid": 11111
}
添加完成,我们可以去查看一下:
[root@server ~]# ansible web -m shell -a 'cat /etc/passwd |grep keer'
192.168.37.122 | SUCCESS | rc=0 >>
keer:x:11111:11111::/home/keer:/bin/bash
192.168.37.133 | SUCCESS | rc=0 >>
keer:x:11111:11111::/home/keer:/bin/bash
② 删除用户
[root@server ~]# ansible web -m user -a 'name=keer state=absent'
192.168.37.122 | SUCCESS => {
"changed": true,
"force": false,
"name": "keer",
"remove": false,
"state": "absent"
}
192.168.37.133 | SUCCESS => {
"changed": true,
"force": false,
"name": "keer",
"remove": false,
"state": "absent"
}
一样的,删除之后,我们去看一下:
[root@server ~]# ansible web -m shell -a 'cat /etc/passwd |grep keer'
192.168.37.122 | FAILED | rc=1 >>
192.168.37.133 | FAILED | rc=1 >>
发现已经没有这个用户了。
2.11 group 模块
该模块主要用于添加或删除组。
常用的选项如下:
gid=
#设置组的GID号name=
#指定组的名称state=
#指定组的状态,默认为创建,设置值为absent
为删除system=
#设置值为yes
,表示创建为系统组
举例如下:
① 创建组
[root@server ~]# ansible web -m group -a 'name=sanguo gid=12222'
192.168.37.122 | SUCCESS => {
"changed": true,
"gid": 12222,
"name": "sanguo",
"state": "present",
"system": false
}
192.168.37.133 | SUCCESS => {
"changed": true,
"gid": 12222,
"name": "sanguo",
"state": "present",
"system": false
}
创建过后,我们来查看一下:
[root@server ~]# ansible web -m shell -a 'cat /etc/group | grep 12222'
192.168.37.122 | SUCCESS | rc=0 >>
sanguo:x:12222:
192.168.37.133 | SUCCESS | rc=0 >>
sanguo:x:12222:
可以看出,我们的组已经创建成功了。
② 删除组
[root@server ~]# ansible web -m group -a 'name=sanguo state=absent'
192.168.37.122 | SUCCESS => {
"changed": true,
"name": "sanguo",
"state": "absent"
}
192.168.37.133 | SUCCESS => {
"changed": true,
"name": "sanguo",
"state": "absent"
}
照例查看一下:
[root@server ~]# ansible web -m shell -a 'cat /etc/group | grep 12222'
192.168.37.122 | FAILED | rc=1 >>
192.168.37.133 | FAILED | rc=1 >>
已经没有这个组的相关信息了。
2.12 script 模块
该模块用于将本机的脚本在被管理端的机器上运行。
该模块直接指定脚本的路径即可,我们通过例子来看一看到底如何使用的:
首先,我们写一个脚本,并给其加上执行权限:
[root@server ~]# vim /tmp/df.sh
#!/bin/bash
date >> /tmp/disk_total.log
df -lh >> /tmp/disk_total.log
[root@server ~]# chmod +x /tmp/df.sh
然后,我们直接运行命令来实现在被管理端执行该脚本:
[root@server ~]# ansible web -m script -a '/tmp/df.sh'
192.168.37.122 | SUCCESS => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.37.122 closed.\r\n",
"stdout": "",
"stdout_lines": []
}
192.168.37.133 | SUCCESS => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.37.133 closed.\r\n",
"stdout": "",
"stdout_lines": []
}
照例查看一下文件内容:
[root@server ~]# ansible web -m shell -a 'cat /tmp/disk_total.log'
192.168.37.122 | SUCCESS | rc=0 >>
Tue Dec 5 15:58:21 CST 2017
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 47G 4.4G 43G 10% /
devtmpfs 978M 0 978M 0% /dev
tmpfs 993M 84K 993M 1% /dev/shm
tmpfs 993M 9.1M 984M 1% /run
tmpfs 993M 0 993M 0% /sys/fs/cgroup
/dev/sda3 47G 33M 47G 1% /app
/dev/sda1 950M 153M 798M 17% /boot
tmpfs 199M 16K 199M 1% /run/user/42
tmpfs 199M 0 199M 0% /run/user/0
192.168.37.133 | SUCCESS | rc=0 >>
Tue Dec 5 15:58:21 CST 2017
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 46G 4.1G 40G 10% /
devtmpfs 898M 0 898M 0% /dev
tmpfs 912M 84K 912M 1% /dev/shm
tmpfs 912M 9.0M 903M 1% /run
tmpfs 912M 0 912M 0% /sys/fs/cgroup
/dev/sda3 3.7G 15M 3.4G 1% /app
/dev/sda1 1.9G 141M 1.6G 9% /boot
tmpfs 183M 16K 183M 1% /run/user/42
tmpfs 183M 0 183M 0% /run/user/0
可以看出已经执行成功了。
2.13 setup 模块
该模块主要用于收集信息,是通过调用facts组件来实现的。
facts组件是Ansible用于采集被管机器设备信息的一个功能,我们可以使用setup模块查机器的所有facts信息,可以使用filter来查看指定信息。整个facts信息被包装在一个JSON格式的数据结构中,ansible_facts是最上层的值。
facts就是变量,内建变量 。每个主机的各种信息,cpu颗数、内存大小等。会存在facts中的某个变量中。调用后返回很多对应主机的信息,在后面的操作中可以根据不同的信息来做不同的操作。如redhat系列用yum安装,而debian系列用apt来安装软件。
① 查看信息
我们可以直接用命令获取到变量的值,具体我们来看看例子:
[root@server ~]# ansible web -m setup -a 'filter="*mem*"' #查看内存
192.168.37.122 | SUCCESS => {
"ansible_facts": {
"ansible_memfree_mb": 1116,
"ansible_memory_mb": {
"nocache": {
"free": 1397,
"used": 587
},
"real": {
"free": 1116,
"total": 1984,
"used": 868
},
"swap": {
"cached": 0,
"free": 3813,
"total": 3813,
"used": 0
}
},
"ansible_memtotal_mb": 1984
},
"changed": false
}
192.168.37.133 | SUCCESS => {
"ansible_facts": {
"ansible_memfree_mb": 1203,
"ansible_memory_mb": {
"nocache": {
"free": 1470,
"used": 353
},
"real": {
"free": 1203,
"total": 1823,
"used": 620
},
"swap": {
"cached": 0,
"free": 3813,
"total": 3813,
"used": 0
}
},
"ansible_memtotal_mb": 1823
},
"changed": false
}
我们可以通过命令查看一下内存的大小以确认一下是否一致:
[root@server ~]# ansible web -m shell -a 'free -m'
192.168.37.122 | SUCCESS | rc=0 >>
total used free shared buff/cache available
Mem: 1984 404 1122 9 457 1346
Swap: 3813 0 3813
192.168.37.133 | SUCCESS | rc=0 >>
total used free shared buff/cache available
Mem: 1823 292 1207 9 323 1351
Swap: 3813 0 3813
可以看出信息是一致的。
② 保存信息
我们的setup模块还有一个很好用的功能就是可以保存我们所筛选的信息至我们的主机上,同时,文件名为我们被管制的主机的IP,这样方便我们知道是哪台机器出的问题。
我们可以看一看例子:
[root@server tmp]# ansible web -m setup -a 'filter="*mem*"' --tree /tmp/facts
192.168.37.122 | SUCCESS => {
"ansible_facts": {
"ansible_memfree_mb": 1115,
"ansible_memory_mb": {
"nocache": {
"free": 1396,
"used": 588
},
"real": {
"free": 1115,
"total": 1984,
"used": 869
},
"swap": {
"cached": 0,
"free": 3813,
"total": 3813,
"used": 0
}
},
"ansible_memtotal_mb": 1984
},
"changed": false
}
192.168.37.133 | SUCCESS => {
"ansible_facts": {
"ansible_memfree_mb": 1199,
"ansible_memory_mb": {
"nocache": {
"free": 1467,
"used": 356
},
"real": {
"free": 1199,
"total": 1823,
"used": 624
},
"swap": {
"cached": 0,
"free": 3813,
"total": 3813,
"used": 0
}
},
"ansible_memtotal_mb": 1823
},
"changed": false
}
然后我们可以去查看一下:
[root@server ~]# cd /tmp/facts/
[root@server facts]# ls
192.168.37.122 192.168.37.133
[root@server facts]# cat 192.168.37.122
{"ansible_facts": {"ansible_memfree_mb": 1115, "ansible_memory_mb": {"nocache": {"free": 1396, "used": 588}, "real": {"free": 1115, "total": 1984, "used": 869}, "swap": {"cached": 0, "free": 3813, "total": 3813, "used": 0}}, "ansible_memtotal_mb": 1984}, "changed": false}
2.14 unarchive模块
这个模块的主要作用就是解压。模块有两种用法:
1:如果参数copy=yes,则把本地的压缩包拷贝到远程主机,然后执行压缩。
2:如果参数copy=no,则直接解压远程主机上给出的压缩包。
- creates:指定一个文件名,当该文件存在时,则解压指令不执行
- dest:远程主机上的一个路径,即文件解压的路径
- grop:解压后的目录或文件的属组
- list_files:如果为yes,则会列出压缩包里的文件,默认为no,2.0版本新增的选项
- mode:解决后文件的权限
- src:如果copy为yes,则需要指定压缩文件的源路径
- owner:解压后文件或目录的属主
实例如下:
1. ansible -i /root/hosts all -m unarchive -a 'src=/usr/loca/src/mysql.tar.gz dest=/usr/local/ copy=no'
与之相对的压缩命令的模块是archive。
2.1.5 archive压缩命令
查看其文档用法如下:
1. [root@docker5 tasks]#-doc -s archive
2. -:Createsoror trees
3. :
4. :# Attributes the file or directory should have. To get supported flags look at the man page for `chattr' on the target system. This string should contain the attributes in
5. asby`lsattr'.
6. path' refers to multiple files by either specifying a glob, a directory or multiple paths in a list.
7. exclude_path: # Remote absolute path, glob, or list of paths or globs for the file or files to exclude from the archive
8. format: # The type of compression to use. Support for xz was added in version 2.5.
9. .
10. :# Mode the file or directory should be. For those used to `/usr/bin/chmod' remember that modes are actually octal numbers (like `0644' or `01777'). Leaving off the leading
11. .As1.8,as(for,`u+rwx' or
12. u=rw,g=r,o=r').
13. .
14. :# (required) Remote absolute path, glob, or list of paths or globs for the file or files to compress or archive.
15. :# Remove any added source files and trees after adding to archive.
16. :# Level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the `range'. `_default' feature works as for `seuser'.
17. :# Role part of SELinux file context, `_default' feature works as for `seuser'.
18. :# Type part of SELinux file context, `_default' feature works as for `seuser'.
19. :# User part of SELinux file context. Will default to system policy, if applicable. If set to `_default', it will use the `user' portion of the policy if available.
20. :# Normally this module uses atomic operations to prevent data corruption or inconsistent reads from the target files, sometimes systems are configured or just broken in
21. this.One,anddoneinunsafe.
22. Thisbooleanunsafeforindonot have any other
23. .Bethisisand.<span class="cnblogs_code_copy"><a title="复制代码"><img id="__LEANOTE_D_IMG_1553658328912"="/api/file/getImage?fileId=5c9b0c3bdd302f0359000074"="复制代码"-mce-src="/api/file/getImage?fileId=5c9b0c3bdd302f0359000074"></a></span>
示例如下:
1. [root@docker5 tasks]#-i /root/hosts master -m archive -a "path=/test/ format=gz dest=/usr/local/src/test.tar.gz"
2. 10.0.102.162|=>{
3. "archived":[#这个目录里面命名有两个文件,但是只压缩了一个,
4. "/test/mysqld"
5. ],
6. "arcroot":"/test/",
7. "changed":true,
8. "dest":"/usr/local/src/test.tar.gz",
9. "expanded_exclude_paths":[],
10. "expanded_paths":[
11. "/test/"
12. ],
13. "gid":0,
14. "group":"root",
15. "missing":[],
16. "mode":"0644",
17. "owner":"root",
18. "secontext":"unconfined_u:object_r:usr_t:s0",
19. "size":189,
20. "state":"file",
21. "uid":0
22. }
23. [root@docker5 tasks]#-i /root/hosts master -m shell -a "chdir=/usr/local/src ls"
24. 10.0.102.162||=0>>
25. mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz
26. test.tar.gz
因为源目录里面有两个文件,但是上面的压缩只压缩了一个文件。
1. [root@docker5 tasks]#-i /root/hosts master -m archive -a "path=/test/* format=gz dest=/usr/local/src/test.tar.gz"
2. 10.0.102.162|=>{
3. "archived":[
4. "/test/mysqld",
5. "/test/test111"
6. ],
7. "arcroot":"/test/",
8. "changed":true,
9. "dest":"/usr/local/src/test.tar.gz",
10. "expanded_exclude_paths":[],
11. "expanded_paths":[
12. "/test/mysqld",
13. "/test/test111"
14. ],
15. "gid":0,
16. "group":"root",
17. "missing":[],
18. "mode":"0644",
19. "owner":"root",
20. "secontext":"unconfined_u:object_r:usr_t:s0",
21. "size":212,
22. "state":"file",
23. "uid":0
24. }#这里虽然压缩了两个文件,但是在解压之后,发现并没有目录,而是把两个文件单独列了出来。[root@docker4 src]#.tar.gz[root@docker4 src]#.tar.gz mysqldtest111[root@docker4 src]#.tar.gz[root@docker4 src]##自己执行tar命令压缩解压[root@docker4 src]# tar zcvf test.tar.gz /test/test//test/mysqld/test/test111[root@docker4 src]# lstest.tar.gz[root@docker4 src]# tar zxvf test.tar.gz test/test/mysqldtest/test111[root@docker4 src]# ls #会有一个test目录test test.tar.gz
2.16 replace模块
这个模块可以根据我们指定的正则表达式替换文件的匹配的内容。
先看一个例子:
- -: change the start script
- #shell: sed -i "s/^datadir=/datadir=\/data\/mysql/" /etc/init.d/mysqld
- :=/etc/init.d/mysqld replace="datadir={{ datadir_name }}"="^datadir="=yes
- #安装MySQL的时候,需要修改MySQL的启动脚本,配置datadir参数,这里两行的作用是一样的。只是在执行playbook的时候,使用shell模块会报出警告说建议使用replcae模块。#模块参数如下:path: 指定远程主机要替换的文件的路径。regexp: 指定在文件中匹配的正则表达式,上面匹配以“datadir=”开头的行replace: 指定替换的文件,就是把上面正则匹配到的文件,替换成这里的内容。backup:表示在对文件操作之前是否备份文件。
2.17 lineinfile模块
这个模块会遍历文本中每一行,然后对其中的行进行操作。
- path参数:必须参数,指定要操作的文件。
- line参数:使用此参数指定文本内容。
- regexp参数:使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。
- state参数:当想要删除对应的文本时,需要将state参数的值设置为absent,absent为缺席之意,表示删除,state的默认值为present。
- backrefs参数:默认情况下,当根据正则替换文本时,即使regexp参数中的正则存在分组,在line参数中也不能对正则中的分组进行引用,除非将backrefs参数的值设置为yes。 backrefs=yes表示开启后向引用,这样,line参数中就能对regexp参数中的分组进行后向引用了,这样说不太容易明白,可以参考后面的示例命令理解。backrefs=yesline对应的内容会被插入到文本的末尾, 不过,如果使用了backrefs=yes,情况就不一样了,当使用正则表达式替换对应行时,同时设置了backrefs=yes,那么当正则没有匹配到任何的行时, 则不会对文件进行任何操作,相当于保持原文件不变。
- insertafter参数:借助insertafter参数可以将文本插入到“指定的行”之后,insertafter参数的值可以设置为EOF或者正则表达式,EOF为EndOfFile之意,表示插入到文档的末尾,默认情况下insertafter的值为EOF,如果将insertafter的值设置为正则表达式,表示将文本插入到匹配到正则的行之后,如果正则没有匹配到任何行,则插入到文件末尾,当使用backrefs参数时,此参数会被忽略。
- insertbefore参数:借助insertbefore参数可以将文本插入到“指定的行”之前,insertbefore参数的值可以设置为BOF或者正则表达式,BOF为BeginOfFile之意, 表示插入到文档的开头,如果将insertbefore的值设置为正则表达式,表示将文本插入到匹配到正则的行之前,如果正则没有匹配到任何行,则插入到文件末尾, 当使用backrefs参数时,此参数会被忽略。
- backup参数:是否在修改文件之前对文件进行备份。
- create参数:当要操作的文件并不存在时,是否创建对应的文件。
在远程主机上创建一个测试文件如下:
1. [root@docker4 test]# cat mysqld
2. [mysqld]
3. skip-grant-tables
4. datadir=/data/mysql
5.
6. datadir is test
7.
8. [mysqld]
9. apped this row
然后再ansible主机上测试:
1. [root@docker5 ~]#.yml
2. ---
3. -: master
4. : root
5. :no
6.
7. :
8. -:module
9. :
10. =/test/mysqld
11. ="^\[mysqld\]$"#匹配以datadir开头的行
12. ="test the row..."#替换为指定的内容
13. [root@docker5 ~]#
执行上面的剧本,
1. [root@docker5 ~]#-playbook -i hosts test.yml
2.
3. PLAY [master]*******************************************************************************************************************************************************************************************
4.
5. TASK [test the lineinfile module]***********************************************************************************************************************************************************************
6. changed:[10.0.102.162]
7.
8. PLAY RECAP **********************************************************************************************************************************************************************************************
9. 10.0.102.162:=1=1=0=0
10.
11. [root@docker5 ~]#
12.
13.
14. #查看内容
15. [root@docker4 test]##这里可以看到只有最后一个匹配的才被替换。
16. [mysqld]
17. skip-grant-tables
18. datadir=/data/mysql
19.
20. datadir is test
21.
22. test the row...
23. apped this<span class="cnblogs_code_copy"><a title="复制代码"><img id="__LEANOTE_D_IMG_1553660315011"="/api/file/getImage?fileId=5c9b0c3bdd302f0359000075"="复制代码"-mce-src="/api/file/getImage?fileId=5c9b0c3bdd302f0359000075"></a></span>
继续测试,在[mysqld]下面添加一行logbin=master.
1. [root@docker5 ~]#.yml
2. ---
3. -: master
4. : root
5. :no
6.
7. :
8. -:module
9. :
10. =/test/mysqld
11. ="log-bin=master"
12. ="^\[mysqld\]$"#设为正则表达式,表示文本插入到匹配行之后。
13.
14. [root@docker5 ~]#-playbook -i hosts test.yml
15.
16. PLAY [master]*******************************************************************************************************************************************************************************************
17.
18. TASK [test the lineinfile module]***********************************************************************************************************************************************************************
19. changed:[10.0.102.162]
20.
21. PLAY RECAP **********************************************************************************************************************************************************************************************
22. 10.0.102.162:=1=1=0=0#查看结果如下:[root@docker4 test]# cat mysqld [mysqld]log-bin=masterskip-grant-tablesdatadir=/data/mysqldatadir is testtest the row...apped this row<span class="cnblogs_code_copy"><a title="复制代码"><img id="__LEANOTE_D_IMG_1553660315013" src="/api/file/getImage?fileId=5c9b0c3bdd302f0359000075" alt="复制代码" data-mce-src="/api/file/getImage?fileId=5c9b0c3bdd302f0359000075"></a></span>
匹配删除以datadir开头的行。
2.18 template的用法
template模块⽤法和copy模块⽤法基本⼀致,它主要⽤于复制配置⽂件。
- ansible-doc -s template
- -:Templatesout.:template
- backup # 拷贝的同时也创建⼀个包含时间戳信息的备份⽂件,默认为no dest= # ⽬标路径
- force # 设置为yes (默认)时,将覆盖远程同名⽂件。设置为no时,忽略同名⽂件的拷贝group # 设置远程⽂件的所属组
- owner # 设置远程⽂件的所有者
- mode # 设置远程⽂件的权限。使⽤数值表⽰时不能省略第⼀位,如0644。
- # 也可以使⽤'u+rwx' or 'u=rw,g=r,o=r'等⽅式设置
- src=# ansible控制器上Jinja2格式的模板所在位置,可以是相对或绝对路径validate #在复制到⽬标主机后但放到⽬标位置之前,执⾏此选项指定的命令。
- # ⼀般⽤于检查配置⽂件语法,语法正确则保存到⽬标位置。
- # 如果要引⽤⽬标⽂件名,则使⽤%s,下⾯的⽰例中的s%即表⽰⽬标机器上的/etc/nginx/nginx.conf
虽然template模块可以按需求修改配置⽂件内容来复制模板到被控主机上,但是有⼀种情况它是不能解决的:不同被控节点所需的配置⽂件差异很⼤,并⾮修改⼏个变量就可以满⾜。例如在centos 6和centos 7上通过yum安装的nginx,它们的配置⽂件内容相差⾮常⼤,且centos 6上的nginx的默认就有⼀个/etc/nginx/conf .d/def ault.conf 。如果直接复制同⼀个模板的nginx配置⽂件到centos 6和centos 7上,很可能导致某⼀版本的nginx不能启动。
ansible centos -m template -a "src=/tmp/nginx.conf.j2 dest=/etc/nginx/nginx.conf mode=0770 owner=root group=root ba ckup=yes validate='nginx -t -c %s'" -o -f 6
这时就有必要在复制模板时挑选对应发⾏版的模板⽂件进⾏配对复制,例如要复制到 centos6上的源模板是nginx6.conf .j2,复制到cent os 7上的源模板是nginx7 .conf .j2。这种⾏为可以称之为"基于变量选择文件或模板"。
---
- tasks:
- name: template file based var
template: src=/templates/nginx{{ ansible_distribution_major_version }}.conf.j2 dest=/etc/nginx/nginx.conf va lidate="/usr/sbin/nginx -t -c %s"
还可以在⽂件内容中指定jinja2的替代变量,在ansible执⾏时⾸先会根据变量内容进⾏渲染,渲染后再执⾏相关模块。例如,此处的template模块,复制⼀个基于发⾏版本号的yum源配置⽂件。以下是某个repo⽂件模板base.repo.j2的内容。
[epel]
name=epel
baseurl=http://mirrors.aliyun.com/epel/{{ ansible_distribution_major_version }}Server/x86_64/
enable=1
gpgcheck=0
再复制即可。