Ansible之ad-hoc
一、什么是ad-hoc
1.什么是ad-hoc
ad-hoc简而言之就是“临时命令”,执行完即结束,并不会保存
2.ad-hoc使用场景
可以用作查看远程机器的进程,或者磁盘,或者拷贝文件
3.ad-hoc命令使用
![]()
[root@m01 ~]# ansible web01 -m shell -a 'free -m'
web01 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 972 129 688 25 154 671
Swap: 1023 0 1023
4.ad-hoc结果返回含义
绿色: 代表被控端主机内容和控制端内容完全一致
黄色: 代表被控端主机发生了内容的改变
红色: 代表出现了故障,提示报错
5.ad-hoc常用的模块
command # 执行shell命令(不支持管道等特殊字符)
shell # 执行shell命令
scripts # 执行shell脚本
yum_repository # 配置yum仓库
yum # 安装软件
copy # 变更配置文件
file # 建立目录或文件
service # 启动与停止服务
systemd # 启动与停止服务
mount # 挂载设备
cron # 定时任务
get_url # 下载软件
firewalld # 防火墙
selinux # selinux
setup # 获取主机信息
5.ansible帮助
#1.查看所有模块(太多了,几乎不用)
[root@m01 ~]# ansible-doc -l
#2.查看指定模块的用法 (注意:按q退出。如果按ctrl+C退出,登录界面会异常,只能关闭重开)
[root@m01 ~]# ansible-doc yum
#3.查看模块参数
[root@m01 ~]# ansible-doc -s yum
二、Ansible命令模块
1.command模块(不识别特殊符号)(不加-m参数默认是command模块)
#默认模块,执行命令
[root@m01 ~]# ansible all -m command -a 'free -m'
web02 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 972 207 585 25 179 581
Swap: 1023 0 1023
web01 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 972 129 686 25 155 670
Swap: 1023 0 1023
#不识别特殊符号
[root@m01 ~]# ansible all -m command -a 'ps -ef | grep httpd'
web02 | FAILED | rc=1 >>
error: garbage option
Usage:
ps [options]
Try 'ps --help <simple|list|output|threads|misc|all>'
or 'ps --help <s|l|o|t|m|a>'
for additional help text.
2.shell模块
[root@m01 ~]# ansible all -m shell -a 'ps -ef | grep httpd'
web01 | CHANGED | rc=0 >>
root 8534 8529 0 00:06 pts/0 00:00:00 /bin/sh -c ps -ef | grep httpd
root 8536 8534 0 00:06 pts/0 00:00:00 grep httpd
web02 | CHANGED | rc=0 >>
root 8264 8259 0 00:06 pts/0 00:00:00 /bin/sh -c ps -ef | grep httpd
root 8266 8264 0 00:06 pts/0 00:00:00 grep httpd
#下面\用于转义,否则ansible无法识别。单引号如果多个,识别会有问题,用单引号双引号混合使用
[root@m01 ~]# ansible all -m shell -a "ifconfig eth0 | awk 'NR==2 {print \$2}'"
web02 | CHANGED | rc=0 >>
10.0.0.8
web01 | CHANGED | rc=0 >>
10.0.0.7
3.script模块
[root@m01 ~]# vim mkdir.sh
#!/bin/bash
mkdir /service
[root@m01 ~]# ansible web_group -m script -a '/root/mkdir.sh'
web02 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to web02 closed.\r\n",
"stderr_lines": [
"Shared connection to web02 closed."
],
"stdout": "",
"stdout_lines": []
}
web01 | FAILED! => {
"changed": true,
"msg": "non-zero return code",
"rc": 1,
"stderr": "Shared connection to web01 closed.\r\n",
"stderr_lines": [
"Shared connection to web01 closed."
],
"stdout": "mkdir: cannot create directory ‘/service’: File exists\r\n",
"stdout_lines": [
"mkdir: cannot create directory ‘/service’: File exists"
]
}
# 参看是否存在了
[root@m01 ~]# ansible web_group -m shell -a 'ls -ld /service'
web01 | CHANGED | rc=0 >>
drwxr-xr-x 4 root root 49 Nov 21 22:30 /service
web02 | CHANGED | rc=0 >>
drwxr-xr-x 2 root root 6 Jan 26 00:28 /service
三、Ansible软件管理模块
1.yum模块
[root@m01 ~]# ansible-doc yum
yum: #这是playbook的写法
name: httpd
state: latest,absent,present
-----------------------------------
name: #name可以写入的内容
httpd #服务名称
http:// #安装软件的网络地址
file #安装本地的rpm包
state: (默认为安装)
latest #安装最新版本的包(一般不用)
present #安装软件包
absent #卸载软件包
-----------------------------------
[root@m01 ~]# vim yum.yml #写个playbook,后缀名都是yml
- host: web01 #主机
tasks: #动作
- name: yum httpd #动作注释
yum: #调用模块
name: httpd
state: present
#1.源安装
# 安装服务httpd(走的是远程机器的yum源)
[root@m01 ~]# ansible web_group -m yum -a 'name=httpd state=present'
相当于在远程机器上:yum install -y httpd
#2.指定网络上安装包
# 安装云上的服务
[root@m01 ~]# ansible web_group -m yum -a 'name=https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.0-2.el7.x86_64.rpm state=present'
相当于在远程机器上: yum install -y https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.0-2.el7.x86_64.rpm
#3.指定本地安装包安装
# 安装本地的rpm包(包一定先传到远程机器上)
[root@m01 ~]# ansible web_group -m yum -a 'name=/tmp/nginx-1.16.1-1.el7.ngx.x86_64.rpm'
相当于在远程机器上:yum localinstall -y /tmp/nginx-1.16.1-1.el7.ngx.x86_64.rpm
2.yum_repository模块
传repo源文件,用的较少,推荐用copy模块
[root@m01 ~]# ansible-doc yum_repository
yum_repository:
name: epel
description: EPEL YUM repo
file: external_repos #定义repo文件的名字(如果没有,就以name参数命名)
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
gpgcheck: no
mirrorlist: http://mirrorlist.repoforge.org/el7/mirrors-rpmforge#定义源列表,可加可不加
enabled: no
state: absent #添加为present(默认为添加),删除为absent
# 查看远程机器上是否有源
[root@web02 ~]# cd /etc/yum.repos.d/
[root@web02 yum.repos.d]# ls
CentOS-Base.repo epel.repo php.repo
#添加yum源 (加\转义,否则$basearch会被当成变量)
[root@web01 ~]# ansible web_group -m yum_repository -a "name=nginx description='nginx repo' baseurl=http://nginx.org/packages/centos/7/\$basearch/ gpgcheck=no enabled=yes"
------------------------------
name #yum源里面[]的内容
description #yum源里面的name
baseurl #指定yum仓库
gpgcheck #是否校验
yes
no
enabled #是否启用仓库
yes
no
state
present #添加仓库
absent #删除仓库
file #指定yum仓库名字
------------------------------
#参看被控制端上添加的yum源
[root@web02 yum.repos.d]# cat /etc/yum.repos.d/nginx.repo
[nginx] #yum_repository模块中的name参数
baseurl = http://nginx.org/packages/centos/7/$basearch/
enabled = 1
gpgcheck = 0
name = nginx repo #yum_repository模块中的description参数
#添加yum源 (file定义repo源名字)
[root@web01 ~]# ansible web_group -m yum_repository -a "name=nginx description='nginx repo' baseurl=http://nginx.org/packages/centos/7/\$basearch/ gpgcheck=no enabled=yes file=lhd"
[root@web02 yum.repos.d]# ls
CentOS-Base.repo epel.repo lhd.repo nginx.repo php.repo
#删除yum源
[root@web01 ~]# ansible web_group -m yum_repository -a "name=nginx description='nginx repo' baseurl=http://nginx.org/packages/centos/7/\$basearch/ gpgcheck=no enabled=yes file=lhd state=absent"
#添加多个内容的repo源(直接在执行一条name不同,file相同的即可)
[root@web01 ~]# ansible web_group -m yum_repository -a "name=nginx description='nginx repo' baseurl=http://nginx.org/packages/centos/7/\$basearch/ gpgcheck=no enabled=yes file=lhd state=present"
[root@web01 ~]# ansible web_group -m yum_repository -a "name=nginx-2 description='nginx repo' baseurl=http://nginx.org/packages/centos/7/\$basearch/ gpgcheck=no enabled=yes file=lhd state=present"
# 注:file不修改的前提下,不修改name则是修改yum源,修改name就是添加一条yum源
四、文件管理模块
1.copy模块
[root@m01 ~]# ansible-doc copy
copy:
src: /srv/myfiles/foo.conf #源文件,管理机上文件或目录
dest: /etc/foo.conf #目标(如果是目录,就推送到该目录下,如果是文件,就会推送为该名称文件)
owner: foo #权限属主(远端服务器必须真实存在)
group: foo #权限属组(远端服务器必须真实存在)
mode: '0644' #文件权限(文件默认644,目录默认755) 小心,最好用默认的不配
backup: yes/no #是否备份(如果之前有文件就备份一份)
content: '# This file was moved to /etc/other.conf' #写一个文件(到远端文件)
follow: yes/no #识别远程文件是否是软链接
force: yes/no #先判断文件是否存在,存在就不推,不存在再推送
#推送文件至远端 (推送至目录,最好把/加上)
[root@m01 yum.repos.d]# ansible 'web_group' -m copy -a 'src=/root/mkdir.sh dest=/service/'
#如果推送目录则src不需要加/
[root@m01 yum.repos.d]# ansible 'web_group' -m copy -a 'src=/var/log/ dest=/tmp/'
[root@m01 ~]# vim /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
#推送仓库文件 (注意这里如果传的是*所有内容,命令是不认识的;可以推送文件夹,里面文件有变动就会覆盖)
[root@m01 yum.repos.d]# ansible web_group -m copy -a 'src=/etc/yum.repos.d/nginx.repo dest=/etc/yum.repos.d/'
#推送一个站点文件,并授权
[root@m01 yum.repos.d]# ansible web_group -m copy -a 'src=/root/index.html dest=/var/www/html owner=root group=root mode=644'
#推送一个站点文件,把远程服务器的原文件备份(推送的文件必须修改内容) 一般不用
[root@m01 yum.repos.d]# ansible web_group -m copy -a 'src=/root/index.html dest=/var/www/html owner=root group=root mode=644 backup=yes'
#远程服务器的原文件名字后面会加一个时间戳(处理起来比较麻烦)
#一般不用这种方式,开一个文件夹存原文件,如果有问题回退,把原文件再次分发
#将指定内容写入指定文件(相当于echo >命令)
[root@m01 ~]# ansible web_group -m copy -a "content='123456' dest=/etc/rsync_password"
如果推送的目标是软链接的情况下,用follow
#web01上做个软链接
[root@web01 html]# ln -s index.html.ori index.html
#这里follow为no不识别软链接,那么就直接拷过去,web01的index.html.ori软链接没了,变成一个文件
[root@m01 yum.repos.d]# ansible web_group -m copy -a 'src=/root/index.html dest=/var/www/html/index.html.ori owner=root group=root mode=644 follow=no'
#这里follow为yes识别软链接,内容会写到软链接链接的文件index.html中,index.html.ori软链接保留
[root@m01 yum.repos.d]# ansible web_group -m copy -a 'src=/root/index.html dest=/var/www/html/index.html.ori owner=root group=root mode=644 follow=no'
2.file模块
[root@m01 ~]# ansible-doc file
file:
path: /etc/foo.conf #要创建的文件或目录
owner: foo
group: foo
mode: '0644'
state: directory absent link
recurse: yes
------------------------------
path: #要创建的文件或目录
state:
directory #创建的是目录
touch #创建的是文件
absent #删除文件
link #创建软链接
src #连接的文件
dest #软链接
owner: foo #文件属主
group: foo #文件属组
mode: '0644' #文件权限
recurse: #是否递归
yes (默认)
no
#注意:
1.当目录本身不存在时,递归创建就会递归授权
2.当目录存在时,递归授权只授权你指定的目录下面的所有内容
------------------------------
#创建目录
[root@m01 ~]# ansible web_group -m file -a 'path=/code state=directory'
相当于远程机器上 mkdir /code
#无论/data/service存不存在,都会创建
[root@m01 ~]# ansible web_group -m file -a 'path=/data/service/new state=directory'
#创建目录并授权
[root@m01 ~]# ansible web01 -m file -a 'path=/file state=directory owner=root group=root mode=777'
#创建文件(上层文件必须存在)
[root@m01 ~]# ansible web_group -m file -a 'path=/data/service/new state=touch'
#创建文件并授权(如果已有该文件,会重新创建并覆盖)
[root@m01 ~]# ansible web_group -m file -a 'path=/data/service/new state=touch owner=adm group=adm mode=777'
#递归授权(默认recurse为yes) (code文件夹已存在,权限不变;wordress,htm,www都不存在,全部授权777)
[root@m01 ~]# ansible web_group -m file -a 'path=/code/wordress/htm/www state=directory owner=adm grou递归授权p=adm mode=777'
#递归授权 (/data/service/new都存在,只改new文件夹权限,new下级文件夹权限不变)
[root@m01 ~]# ansible web_group -m file -a 'path=/data/service/new state=directory owner=adm group=adm mode=777'
3.fetch模块
从远程主机提取文件至 ansible 的主控端,copy 相反,不支持目录
#查看帮助
[root@ubuntu ~]# ansible-doc -s fetch
#常用选项
src=/path/file #远程主机上的文件路径
fail_on_missing=yes|no #默认yes,无法获取远程主机文件时,显示失败
dest=/path #ansible主机上的保存路径,不存在会自动创建
[root@ubuntu ~]# ansible "10.0.0.206 10.0.0.150" -m fetch -a "src=/etc/issue
dest=./ansible-fetch"
10.0.0.150 | CHANGED => {
"changed": true,
"checksum": "2cf4509acb4ba67280d4dff829ef4c550a45bb4b",
"dest": "/root/ansible-fetch/10.0.0.150/etc/issue",
"md5sum": "7886cd1627ee2af067882f3ba048cb17",
"remote_checksum": "2cf4509acb4ba67280d4dff829ef4c550a45bb4b",
"remote_md5sum": null
}
10.0.0.206 | CHANGED => {
"changed": true,
"checksum": "133e53602931fc3b50bc07e2d8fd5af745a4d531",
"dest": "/root/ansible-fetch/10.0.0.206/etc/issue",
"md5sum": "d5faf84af6529c6e6a364f164e953ff6",
"remote_checksum": "133e53602931fc3b50bc07e2d8fd5af745a4d531",
"remote_md5sum": null
}
#分开存放
[root@ubuntu ~]# tree ansible-fetch/
ansible-fetch/
├── 10.0.0.150
│ └── etc
│ └── issue
└── 10.0.0.206
└── etc
└── issue
4 directories, 2 files
setup 模块
#此模块主要用来从远程主机上收集相关信息在 ansible 主机上显示,由于需要收集的信息较多,此模块执行较慢。
#查看帮助
[root@ubuntu ~]# ansible-doc -s setup
#常用选项
filter=filed1,filed2 #只显示指定字段,可以用通配符,可以写多个,可以用 !取反
gather_timeout=10 #超时时长,默认10S
#显示本机所有信息
[root@ubuntu ~]# ansible 127.0.0.1 -m setup
#收集所有字段
[root@ubuntu ~]# ansible 10.0.0.206 -m setup
......
#只显示主机名
[root@ubuntu ~]# ansible 10.0.0.206 -m setup -a 'filter=ansible_hostname'
#显示主机名和IPV4
[root@ubuntu ~]# ansible 10.0.0.206 -m setup -a 'filter=ansible_hostname,all_ipv4_addresses'
sysctl
#sysctl 模块用来修改远程主机上的内核参数
#查看帮助
[root@ubuntu ~]# ansible-doc -s sysctl
#常用选项
name=str #参数名称
val=str #参数值
reload=yes|no #默认yes,调用 /sbin/sysctl -p 生效
state=present|absent #是否保存到文件,默认present
sysctl_file=/path/file #指定保存文件路径,默认 /etc/sysctl.conf
sysctl_set=yes|no #是否使用systctl -w 校验,默认no
#修改内核参数,并写文件
[root@ubuntu ~]# ansible 10.0.0.206 -m sysctl -a 'name=net.ipv4.ip_forward
value=1'
10.0.0.206 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true
}
#在远程主机上查看
[root@ubuntu ~]# sysctl -a | grep "ip_forward ="
net.ipv4.ip_forward = 1
#查看内核参数
[root@ubuntu ~]#sysctl -p
[root@ubuntu ~]# cat /etc/sysctl.conf | grep ip_forward
net.ipv4.ip_forward=1
#从文件中删除
[root@ubuntu ~]# ansible 10.0.0.206 -m sysctl -a 'name=net.ipv4.ip_forward
state=absent'
10.0.0.206 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true
}
#远程主机的文件中没有了
[root@ubuntu ~]# cat /etc/sysctl.conf | grep ip_forward
#但值没有刷新,从文件中同步,文件没有此项了,所以此项不会改变
[root@ubuntu ~]# sysctl -a | grep "ip_forward ="
net.ipv4.ip_forward = 1