Linux架构23 Ansible之ad-hoc, 命令模块(command, shell, script), 软件管理模块(yum, yum_repository), 文件管理模块(copy, file, fetch),setup,sysctl内核参数
一、什么是ad-hoc
1.什么是ad-hoc
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
绿色: 代表被控端主机内容和控制端内容完全一致
黄色: 代表被控端主机发生了内容的改变
红色: 代表出现了故障,提示报错
command # 执行shell命令(不支持管道等特殊字符) shell # 执行shell命令 scripts # 执行shell脚本 yum_repository # 配置yum仓库 yum # 安装软件 copy # 变更配置文件 file # 建立目录或文件 service # 启动与停止服务 systemd # 启动与停止服务 mount # 挂载设备 cron # 定时任务 get_url # 下载软件 firewalld # 防火墙 selinux # selinux setup # 获取主机信息
#1.查看所有模块(太多了,几乎不用) [root@m01 ~]# ansible-doc -l #2.查看指定模块的用法 (注意:按q退出。如果按ctrl+C退出,登录界面会异常,只能关闭重开) [root@m01 ~]# ansible-doc yum #3.查看模块参数 [root@m01 ~]# ansible-doc -s yum
#默认模块,执行命令 [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.
[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
[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
[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
[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源
[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'
[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'
从远程主机提取文件至 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