admin 管理员组

文章数量: 887017

Ansible介绍与发展历史

Ansileb发展史

作者:Michael DeHaan( Cobbler 与 Func 作者)ansible 的名称来自科幻小说《安德的游戏》中跨越时空的即时通信工具,使用它可以在相距数光年的距离,远程实时控制前线的舰队战斗2012-03-09,发布0.0.1版,2015-10-17,Red Hat宣布1.5亿美元收购;

官网:https://www.ansible/
官方文档:https://docs.ansible/

在这里插入图片描述

Ansible功能介绍

​ 批量执行远程命令,可以对远程的多台主机同时进行命令的执行批量安装和配置软件服务,可以对远程的多台主机进行自动化的方式配置和管理各种服务编排高级的企业级复杂的IT架构任务, Ansible的Playbook和role可以轻松实现大型的IT复杂架构提供自动化运维工具的开发API, 有很多运维工具,如jumpserver就是基于 ansible 实现自动化管理功能

ansible的特点

  • 模块化:调用特定的模块完成特定任务,支持自定义模块,可使用任何编程语言写模块
  • Paramiko(python对ssh的实现),PyYAML,Jinja2(模板语言)三个关键模块
  • 基于Python语言实现
  • 部署简单,基于python和SSH(默认已安装),agentless,无需代理不依赖PKI(无需ssl)
  • 安全,基于OpenSSH
  • 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况,此特性非绝对
  • 支持playbook编排任务,YAML格式,编排任务,支持丰富的数据结构
  • 较强大的多层解决方案 role

Ansible结构介绍

Ansible 组成

组合INVENTORY、API、MODULES、PLUGINS的绿框,为ansible命令工具,其为核心执行工具

  • INVENTORY:Ansible管理主机的清单/etc/anaible/hosts
  • MODULES:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
  • PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
  • API:供第三方程序调用的应用程序编程接口

Ansible命令执行的来源

  • USER 普通用户,即SYSTEM ADMINISTRATOR
  • PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执
  • 行,通常是JSON格式的YML文件
  • CMDB(配置管理数据库) API 调用
  • PUBLIC/PRIVATE CLOUD API调用
  • USER-> Ansible Playbook -> Ansibile

Ansible的注意事项

  • 执行ansible的主机一般称为管理端, 主控端,中控,master或堡垒机
  • 主控端Python版本需要2.6或以上
  • 被控端Python版本小于2.4,需要安装python-simplejson
  • 被控端如开启SELinux需要安装libselinux-python
  • windows 不能做为主控端

Ansible的安装与入门

使用yum安装Ansible(推荐)

配置epel源
tee /etc/yum.repos.d/Base.repo <<EOF
[base]
name=base
baseurl=file:///mnt/cdrom
baseurl=https://mirrors.aliyun/centos/$releasever/os/$basearch/
baseurl=https://mirrors.cloud.tencent/centos/$releasever/os/$basearch/
baseurl=https://repo.huaweicloud/centos/$releasever/os/$basearch/
baseurl=https://mirrors.tuna.tsinghua.edu/centos/$releasever/os/$basearch/
gpgcheck=0
enabled=1

[EPEL]
name=EPEL
baseurl=https://mirrors.aliyun/epel/$releasever/$basearch/
baseurl=https://mirrors.cloud.tencent/epel/$releasever/$basearch/
baseurl=https://mirrors.huaweicloud/epel/$releasever/$basearch/
baseurl=https://mirrors.tuna.tsinghua.edu/epel/$releasever/$basearch/
gpgcheck=0
enabled=1

[extras-1]
name=extras-1
baseurl=https://mirrors.aliyun/centos/$releasever/extras/$basearch/
baseurl=https://mirrors.cloud.tencent/centos/$releasever/extras/$basearch/
baseurl=https://mirrors.huaweicloud//centos/$releasever/extras/$basearch/
baseurl=https://mirrors.tuna.tsinghua.edu/centos/$releasever/extras/$basearch/
gpgcheck=0
enabled=1
EOF
安装ansible
yum info ansible
yum install ansible -y
ansible --version

编译安装Ansible

下载编译工具
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
下载安装包
wget https://releases.ansible/ansible/ansible-1.5.4.tar.gz
开始编译安装
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible

PIP安装

# pip 是安装Python包的管理器,类似 yum
yum install python-pip
pip install --upgrade pip
pip install ansible --upgrade

Ansible相关配置文件

配置文件

  • /etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性,也可以在项目的目录中创建此文件, 当前目录下如果也有ansible.cfg,则此文件优先生效,建议每个项目目录下,创建独有的ansible.cfg文 件
  • /etc/ansible/hosts 主机清单
  • /etc/ansible/roles/ 存放角色的目录

ansible主配置文件

Ansible 的配置文件可以放在多个不同地方,优先级从高到低顺序如下

ANSIBLE_CONFIG #环境变量,注意此项用 ansible --version 看不到,但可以生效
./ansible.cfg   #当前目录下的ansible.cfg
~/.ansible.cfg #当前用户家目录下的.ansible.cfg
/etc/ansible/ansible.cfg  #系统默认配置文件

Ansible 的默认配置文件 /etc/ansible/ansible.cfg ,其中大部分的配置内容无需进行修改

[defaults]
#inventory     = /etc/ansible/hosts #主机列表配置文件
#library = /usr/share/my_modules/ #库文件存放目录
#remote_tmp = $HOME/.ansible/tmp #临时py命令文件存放在远程主机目录
#local_tmp     = $HOME/.ansible/tmp #本机的临时命令执行目录
#forks         = 5   #默认并发数
#sudo_user     = root #默认sudo 用户
#ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码
#ask_pass     = True   
#remote_port   = 22		#默认使用端口
#host_key_checking = False     #检查对应服务器的host_key,建议取消此行注释,实现第一次连接自动信任目标主机

#log_path=/var/log/ansible.log #日志文件,建议启用
#module_name = command   #默认模块,可以修改为shell模块
[privilege_escalation] #普通用户提权配置
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False

范例:优先度对比

[root@Ansible-Master ~16:34]#ansible --version
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Apr  2 2020, 13:16:51) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
[root@Ansible-Master ~16:34]#cp /etc/ansible/ansible.cfg .
[root@Ansible-Master ~16:34]#ansible --version
ansible 2.9.27
  config file = /root/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Apr  2 2020, 13:16:51) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

inventory 主机清单文件

​ ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory 主机清单文件中将其分组组织默认的inventory file为 /etc/ansible/hostsinventory file可以有多个,且也可以通过Dynamic Inventory来动态生成。
注意: 生产建议在每个项目目录下创建项目独立的hosts文件

官方文档
https://docs.ansible/ansible/latest/user_guide/intro_inventory.html
主机清单格式

nventory文件遵循INI文件风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组
中;
此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明;
如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机;

**Inventory 参数说明
ansible_ssh_host #将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port #ssh端口号.如果不是默认的端口号,通过此变量设置.这种可以使用 ip:端口
192.168.1.100:2222
ansible_ssh_user #默认的 ssh 用户名
ansible_ssh_pass #ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass #sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8) #sudo 命令路径(适用于1.8及以上版本)
ansible_connection #与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默
认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来
判断'ssh' 方式是否可行.
ansible_ssh_private_key_file #ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的
情况.
ansible_shell_type #目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为
'csh''fish'.
ansible_python_interpreter #目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 
或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python 不是 2.X 版本的
Python.之所以不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 
可执行程序名不可为 python以外的名字(实际有可能名为python26).与
ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....

范例:

[test]
10.0.0.8 ansible_connection=local #指定本地连接,无需ssh配置
#ansible_connection=ssh 需要StrictHostKeyChecking no
10.0.0.7 ansible_connection=ssh ansible_ssh_port=2222 ansible_ssh_user=wang
ansible_ssh_password=magedu
10.0.0.6 ansible_connection=ssh ansible_ssh_user=root
ansible_ssh_password=123456
#执行ansible命令时显示别名,如web01
[websrvs]
web01 ansible_ssh_host=10.0.0.101
web02 ansible_ssh_host=10.0.0.102
[websrvs:vars]
ansible_ssh_password=magedu
some_host ansible_ssh_port=2222 ansible_ssh_user=manager
aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host ansible_python_interpreter=/usr/local/bin/python
ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3

Ansible相关工具

  • /usr/bin/ansible 主程序,临时命令执行工具
  • /usr/bin/ansible-doc 查看配置文档,模块功能查看工具,相当于man
  • /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具,相当于脚本 /usr/bin/ansible-pull 远程执行命令的工具
  • /usr/bin/ansible-vault 文件加密工具
  • /usr/bin/ansible-console 基于Console界面与用户交互的执行工具 /usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台

利用ansible实现管理的主要方式:

  • Ansible Ad-Hoc 即利用ansible命令,主要用于临时命令使用场景 Ansible
  • playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程

Ansible使用前准备

ansible 相关工具大多数是通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能 建议:使用此工具前,先配置ansible主控端能基于密钥认证的方式联系各个被管理节点

范例:利用sshpass批量实现基于key验证脚本1

!/bin/bash
rpm -q sshpass &> /dev/null || yum -y install sshpass
[ -f /root/.ssh/id_rsa ] || ssh-keygen -f /root/.ssh/id_rsa -P ''
export SSHPASS=magedu
while read IP;do
sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $IP
done < hosts.list

范例:基于key验证的脚本2

#!/bin/bash
IPLIST="
192.168.213.121
192.168.213.122
192.168.213.123
192.168.213.124
192.168.213.125"
rpm -q sshpass &> /dev/null || yum -y install sshpass
[ -f /root/.ssh/id_rsa ] || ssh-keygen -f /root/.ssh/id_rsa -P ''
export SSHPASS=123456
for IP in $IPLIST;do
{ sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $IP; } &
done
wait

#!/bin/bash
#较少node场景下使用,注意:依赖sshpass包
PASS="Huawei12#$"
IP_list=(
192.168.213.121
192.168.213.122
)
#环境清理
rm -rf /root/.ssh/id_rsa
#生成ssh_key的rsa文件
ssh-keygen -f /root/.ssh/id_rsa -t rsa -P ''
#拷贝公钥
for i in "${IP_list[@]}";do
sshpass -p "$PASS" ssh-copy-id -i root@"$i"
done

范例:实现基于key验证的脚本

#!/bin/bash
#较多node场景使用;注意:依赖sshpass包
PASS="redhat"
#设置网段最后的地址
END="160"
NET_name="eth0"
IP="$(ip a s "$NET_name" | awk -F'[ /]+' 'NR==3{print $3}')"
Segment=${IP%.*}.

#环境清理,不清理会需要输入y,即覆盖
rm -rf /root/.ssh/id_rsa
#生成可连通的主机列表
[ -e /root/SCANIP.log ] && echo "" > /root/SCANIP.log || touch /root/SCANIP.log
for((i=1;i<="$END";i++));do
ping -c1 -w1 "$Segment""$i" &>/dev/null && echo  "$Segment""$i" >/root/SCANIP.log &
done
#删除空行
sed -Ei "/^$/d" /root/SCANIP.log
#生成ssh_key的rsa文件
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa
#拷贝公钥
while read -r line ;do
        sshpass -p "$PASS" ssh-copy-id -i  root@"$line"
        done</root/SCANIP.log

ansible-doc:获取指定模块的帮助文档

格式:

ansible-doc [options] [module...]
-l, --list #列出可用模块
-s, --snippet #显示指定模块的playbook片段

列出所有模块,版本2.9.27有3387个模块,不同版本会有一定的差异;

ansible-doc -l 

列出指定模块帮助

ansible-doc -s module_name

ansible Ad-Hoc的 执行方式

ansible Ad-Hoc说明:

Ansible Ad-Hoc的执行方式主要的工具就是ansible命令:
#格式:	ansible <host-pattern> [-m module_name] [-a args]

常用选项说明:

显示版本	--version
指定模块,默认为command	-m module
详细过程 -vv -vvv更详细	-v
显示主机列表,可简写 --list	-list-hosts
检查,并不执行	-C, --check
执行命令的超时时间,默认10s	-T, --timeout=TIMEOUT
提示输入ssh连接密码,默认Key验证	-k, --ask-pass
执行远程执行的用户,默认root	-u, --user=REMOTE_USER
代替旧版的sudo 切换	-b, --become
指定sudo的runas用户,默认为root	--become-user=USERNAME
提示输入sudo时的口令	-K, --ask-become-pass
指定并发同时执行ansible任务的主机数	-f FORKS, --forks FORKS

范例:调用shell模块查看shadow文件

#修改被控制端的suduers文件,添加用户ALL=(ALL) NOPASSWD: ALL字段:
sed -ri '/## Same thing without a password/a\xiang ALL =(ALL) NOPASSWD: ALL /etc/sudoers
#调用shell模块查看shadow
ansible 192.168.213.122 -m shell -a 'sudo cat /etc/shadow |head -5' -u xiang -k -b
[root@Ansible-Master ~14:18]#ansible 192.168.213.123 -m shell -a 'sudo cat /etc/shadow|head -5' -u xiang -k 
SSH password: 
[WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running sudo
192.168.213.123 | CHANGED | rc=0 >>
root:$6$nZpI0Gve/q3y/vLW$k8QocsCR4x65nEqLaFsHhQGR8eYibTP.ixE5pzNY.8qTz3OkwWWIs8c4Z5QZJ6VZ8Lv0YVNvVoapARSpAuHDm1::0:99999:7:::
bin:*:18353:0:99999:7:::
daemon:*:18353:0:99999:7:::
adm:*:18353:0:99999:7:::
lp:*:18353:0:99999:7:::

ansible的Host-pattern

用于匹配被控制的主机列表

all:表示所有inventory中的所有主机

范例:调用ping模块测试所有主机连通性

#查看ansible hosts文件中所有的主机
[root@Ansible-Master ~14:30]#cat /etc/ansible/hosts |grep -Ev "^#|^$"
[local]
192.168.213.101 ansible_connection=local
[webservs]
192.168.213.122:22 hname=www1 domain=slave01
192.168.213.123:22 hname=www2 domain=slave02
[webservs:vars]
mark="-"
[all:vars]
domain=xiangdeming
[dbservs]
192.168.213.124:22
[appservs]
192.168.213.101:22
192.168.213.122:22
192.168.213.123:22
192.168.213.124:22

#调用ping模块测试所有主机的连通性,当前例子可以all测试所有主机(共4台),且两通两不通
[root@Ansible-Master ~14:30]#ansible all -m ping 
192.168.213.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.122 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.122 port 22: No route to host", 
    "unreachable": true
}
192.168.213.124 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.124 port 22: No route to host", 
    "unreachable": true
}

"*"通配符

#通配符”*“类似于all,可以匹配任意主机或字符
[root@Ansible-Master ~14:33]#ansible "*" -m ping
192.168.213.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.122 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.122 port 22: No route to host", 
    "unreachable": true
}
192.168.213.124 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.124 port 22: No route to host", 
    "unreachable": true
}

[root@Ansible-Master ~14:36]#ansible 192.168.213.* -m ping
192.168.213.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.122 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.122 port 22: No route to host", 
    "unreachable": true
}
192.168.213.124 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.124 port 22: No route to host", 
    "unreachable": true
}

#多台指定主机,使用”“,并在主机之前用空格隔开;
[root@Ansible-Master ~14:37]#ansible "192.168.213.101 192.168.213.122" -m ping
192.168.213.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.122 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.122 port 22: No route to host", 
    "unreachable": true
}

主机之间或的关系

#指定两台主机或关系,使用""并IP或别名组之间使用:隔开;
[root@Ansible-Master ~14:40]#ansible "192.168.213.101:192.168.213.123" -m ping
192.168.213.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

逻辑与

#查看主机列表
[root@Ansible-Master ~14:53]#cat /etc/ansible/hosts |grep -Ev "^#|^$"
[local]
192.168.213.101 ansible_connection=local
[webservs]
192.168.213.123:22
[webservs:vars]
mark="-"
[all:vars]
domain=xiangdeming
[dbservs]
192.168.213.124:22
[appservs]
192.168.213.101:22
192.168.213.122:22
192.168.213.123:22
192.168.213.124:22
#在webservs中且在dbservs组中的主机只有192.168.213.123:22
[root@Ansible-Master ~14:55]#ansible "webservs:&appservs" -m ping
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

逻辑非

#查看主机列表
[root@Ansible-Master ~14:53]#cat /etc/ansible/hosts |grep -Ev "^#|^$"
[local]
192.168.213.101 ansible_connection=local
[webservs]
192.168.213.122:22
192.168.213.123:22
[webservs:vars]
mark="-"
[all:vars]
domain=xiangdeming
[dbservs]
192.168.213.124:22
[appservs]
192.168.213.101:22
192.168.213.123:22
192.168.213.124:22
#在webservs中不存在于dbservs组中的主机只有192.168.213.122:22
[root@Ansible-Master ~15:11]#ansible 'webservs:!appservs' -m ping
192.168.213.122 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

综合逻辑

#查看主机列表
[root@Ansible-Master ~15:21]#grep -Ev "^#|^$" /etc/ansible/hosts 
[local]
192.168.213.101 ansible_connection=local
[webservs]
192.168.213.122:22
192.168.213.123:22
[webservs:vars]
mark="-"
[all:vars]
domain=xiangdeming
[dbservs]
192.168.213.124:22
[appservs]
192.168.213.121:22
192.168.213.124:22
[ftpservs]
192.168.213.125:22

#webservs与dbservs中的主机在appservs中存在的而在ftpservs中不存在的主机;
[root@Ansible-Master ~15:21]#ansible 'webservs:dbservs:&appservs:!ftpservs' -m ping
192.168.213.124 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.124 port 22: No route to host", 
    "unreachable": true
}

正则表达式

#查看主机列表
[root@Ansible-Master ~15:29]#grep -Ev "^#|^$" /etc/ansible/hosts 
[local]
192.168.213.101 ansible_connection=local
[webservs]
web1.example
web2.example
[webservs:vars]
mark="-"
[all:vars]
domain=xiangdeming
[dbservs]
db[1:3].example
[appservs]
192.168.213.[120:129]:22
[ftpservs]
192.168.213.130:22

#以web

并发控制

#同时执行多台主机sleep 5,#单台主机执行sleep 5,这里是3台一起执行的,具体的需自行执行
[root@Ansible-Master ~16:09]#ansible appservs  -a "sleep 5" -f3
192.168.213.121 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.121 port 22: No route to host", 
    "unreachable": true
}
192.168.213.122 | CHANGED | rc=0 >>

192.168.213.123 | CHANGED | rc=0 >>

192.168.213.124 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.124 port 22: No route to host", 
    "unreachable": true
}

#单台主机执行sleep 5,这里是一台一台执行的;具体的需自行执行
[root@Ansible-Master ~16:09]#ansible appservs  -a "sleep 5" -f1
192.168.213.121 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.121 port 22: No route to host", 
    "unreachable": true
}
192.168.213.122 | CHANGED | rc=0 >>

192.168.213.123 | CHANGED | rc=0 >>

192.168.213.124 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.213.124 port 22: No route to host", 
    "unreachable": true
}

ansible的执行过程

  1. 加载自己的配置文件,默认/etc/ansible/ansible.cfg
  2. 加载自己对应的模块文件,如:command
  3. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户
  4. /root/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
  5. 给文件+x执行
  6. 执行并返回结果
  7. 删除临时py文件,退出

Ansible的执行状态

  • 绿色:执行成功并需要做改变的操作;
  • 黄色:执行 成功并且对目标主机做出了改变或执行了某些语句的操作,可以通过change_when:false关闭;
  • 红色:执行失败

ansible-console

此工具可交互执行命令,支持tab,ansible 2.0+新增

提示符格式

#	执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$
常用子命令
  • 设置并发数: forks n 例如: forks 10
  • 切换组:cd 主机组 例如: cd web
  • 列出当前组主机列表: list
  • 列出所有的内置命令: ?或help
常用参数
positional arguments:
  pattern               # 连接的主机地址,需在主机清单中

optional arguments:
  --ask-vault-pass      # 加密playbook文件时提示输入密码
  --list-hosts          # 列出执行匹配到的主机,但并不会执行
  --playbook-dir BASEDIR    # 由于此工具不使用剧本,因此将其用作 替换剧本目录
  --step                #one-step-at-a-time: confirm each task before running
  --syntax-check        # 检查Playbook中的语法书写
  --vault-id VAULT_IDS  # vault id
  --vault-password-file # vault 密码文件
  --version             # 显示程序的版本号,配置文件位置,配置的模块搜索路径,模块位置,可执行文件位置
  -C, --check           don't make any changes; instead, try to predict some
  -C, --check           # 模拟执行,不会真正在机器上执行(查看执行会产生什么变化)
  -D, --diff            # 当更新的文件数及内容较少时,该选项可显示这些文件不同的地方,该选项结合-C用会有较好的效果
  -M MODULE_PATH, --module-path MODULE_PATH    # 要执行的模块的路径
  -f FORKS, --forks FORKS    # 并行任务数。FORKS被指定为一个整数,默认是5
  -h, --help            # 命令帮助文档
  -i INVENTORY, --inventory INVENTORY, --inventory-file INVENTORY    # 指定要读取的Inventory文件
  -l SUBSET, --limit SUBSET    # 限定执行的主机范围
  -v, --verbose         # 执行详细输出 (-vvv for more, -vvvv to enable connection debugging)

权限提升参数:
 
  --become-method BECOME_METHOD    # 要使用的权限提升方法(默认=sudo),使用 `ansible-doc -t become -l` 列出有效的选择
  --become-user BECOME_USER    # 以此用户身份运行操作(默认=root)
  -K, --ask-become-pass    # 要求提权的密码
  -b, --become          # 设置为yes激活权限提升。

连接参数:
 
  --private-key PRIVATE_KEY_FILE, --key-file PRIVATE_KEY_FILE    # 使用此文件的连接进行验证
  --scp-extra-args SCP_EXTRA_ARGS    # 指定仅传递给 scp 的额外参数(例如 -l)
  --sftp-extra-args SFTP_EXTRA_ARGS    # 指定仅传递给 sftp 的额外参数(例如 -f、-l)
  --ssh-common-args SSH_COMMON_ARGS    # 指定要传递给 sftp/scp/ssh 的通用参数
  --ssh-extra-args SSH_EXTRA_ARGS    # 指定仅传递给 ssh 的额外参数(例如 -R)
  -T TIMEOUT, --timeout TIMEOUT    # 连接超时时间,单位:秒,默认 10 秒
  -c CONNECTION, --connection CONNECTION    # 要使用的连接类型,默认是 smart
  -k, --ask-pass        # 询问连接密码,也就说,使用密码访问的话,需要加此参数
  -u REMOTE_USER, --user REMOTE_USER    # 以此用户身份连接,默认为 None

范例:进入console界面

[root@Ansible-Master ~16:42]#ansible-console
Welcome to the ansible console.
Type help or ? to list commands.

root@all (6)[f:5]$ 

范例:组切换

[root@Ansible-Master ~22:28]#ansible-console
Welcome to the ansible console.
Type help or ? to list commands.

root@all (7)[f:5]$ cd webservs
root@webservs (2)[f:5]$ cd dbservs
root@dbservs (1)[f:5]$ list
db01
root@dbservs (1)[f:5]$ cd webservs
root@webservs (2)[f:5]$ list
192.168.213.122
192.168.213.123
root@webservs (2)[f:5]$ 

ansible-vault

此工具可以用于加密解密yml文件

ansible-vault的命令格式:

#	ansible-vault [create|decrypt|edit|encrypt|rekey|view]

范例:ansible-vault对yml文件的加密解密修改等操作

cat hello.yml
---
#hello word yml file
- hosts: webservs
  remote_user: root
  gather_facts: no
  
  tasks:
  	- name: hello word
  	  command: /usr/bin/wall hello word

ansible-vault encrypt hello.yml #加密
[root@Ansible-Master ~22:46]#ansible-vault encrypt hello.yml
New Vault password: 
Confirm New Vault password: 
Encryption successful
[root@Ansible-Master ~22:49]#vim hello.yml 
[root@Ansible-Master ~22:55]#cat hello.yml 
$ANSIBLE_VAULT;1.1;AES256
31316439613433353866623232373436636332393361386137336634376463333163343762356261
3663396166363930383266633862383861653239623066370a363766653332613165336230333230
33633335643930343866626336613562363734626364636162333838353933376235353737323164
6238633539633432370a316263613864613933636462303338633236313265633933373735383261
30633930326630353362383063633834336431303161646533313761623062383534343931303664
32623932336463363864353034336132343636343537353830633764356332653965396532666462
64663535643563653164643865386238643738376363393165386566636430306161663362616561
34653066393731343366633131626332346338646366306130616462643862366639373833363135
38363337393266663836336361363638366663636135666435663230333935626634616137353830
37663737643332663533643761306438653035393764626130643666633764326332336163333563
61653263373563386330383237313430386366353066616666626234373630636666646435346238
65323530393064306164633132383238663233636365623362356438626631363534343339643536
6337

ansible-vault decrypt hello.yml #解密
[root@Ansible-Master ~22:55]#ansible-vault decrypt hello.yml
Vault password: 
Decryption successful
[root@Ansible-Master ~22:58]#cat hello.yml
---
#hello word yml file
- hosts: webservs
  remote_user: root
  gather_facts: no
  
  tasks:
      - name: hello word
        command: /usr/bin/wall hello word

ansible-vault view hello.yml #查看
[root@Ansible-Master ~22:59]#ansible-vault encrypt hello.yml
New Vault password: 
Confirm New Vault password: 
Encryption successful
[root@Ansible-Master ~22:59]#ansible-vault view hello.yml
Vault password: 
---
#hello word yml file
- hosts: webservs
  remote_user: root
  gather_facts: no
  
  tasks:
      - name: hello word
        command: /usr/bin/wall hello word


ansible-vault edit hello.yml #编辑加密文件
[root@Ansible-Master ~23:01]#ansible-vault edit hello.yml 
Vault password: 
---
#hello word yml file
- hosts: webservs
  remote_user: root
  gather_facts: no

  tasks:
      - name: hello word
        command: /usr/bin/wall hello word


ansible-vault rekey hello.yml #修改口令
[root@Ansible-Master ~23:08]#ansible-vault rekey hello.yml 
Vault password: 
New Vault password: 
Confirm New Vault password: 
Rekey successful


ansible-vault create new.yml #创建新文件
[root@Ansible-Master ~23:11]#ansible-vault create new.yml
New Vault password: 
Confirm New Vault password: 
[root@Ansible-Master ~23:16]#ansible-vault view new.yml
Vault password: 
1234455

ansible-galaxy

Galaxy 是一个免费网站, 类似于github网站, 网站上发布了很多的共享的roles角色。

Ansible 提供了ansible-galaxy命令行工具连接 https://galaxy.ansible 网站下载相应的roles, 进行 init(初始化、search( 查拘、install(安装、 remove(移除)等操作。

范例:

#搜索项目
[root@Ansible-Master ~23:11]# ansible-galaxy search lamp
#列出所有已安装的galaxy
[root@Ansible-Master ~23:11]# ansible-galaxy list
#安装galaxy,默认下载到~/.ansible/roles下
[root@Ansible-Master ~23:11]# ansible-galaxy install geerlingguy.mysql
[root@Ansible-Master ~23:11]# ansible-galaxy install geerlingguy.redis
#删除galaxy
[root@Ansible-Master ~23:11]# ansible-galaxy remove geerlingguy.redis

Aansible常用模块

2015年底270多个模块,2016年达到540个,2018年01月12日有1378个模块,2018年07月15日1852 个模块,2019年05月25日(ansible 2.7.10)时2080个模块,2020年03月02日有3387个模块

参考文档

虽然模块众多,但最常用的模块也就2,30个而已,针对特定业务只用10几个模块 常用模块帮助文档参考:

https://docs.ansible/ansible/2.9/modules/modules_by_category.html
https://docs.ansible/ansible/2.9/modules/list_of_all_modules.html
https://docs.ansible/ansible/latest/modules/list_of_all_modules.html
https://docs.ansible/ansible/latest/modules/modules_by_category.html

Command模块

功能
  • 在远程主机执行命令,此为默认模块,可忽略 -m 选项
  • 注意:此命令不支持 $VARNAME < > | ; & 等,可能用shell模块实现
  • 注意:此模块不具有幂等性
常用参数
argv:将命令作为列表传输,而非字符串,且只能提供字符串或列表形式,不能同时提供两者,必须提供其中一种
chdir:运行命令前,切换到的目录
free_form参数 :必须参数,指定需要远程执行的命令。需要说明一点,free_form 参数与其他参数(如果想要使用一个参数,那么则需要为这个参数赋值,也就是name=value模式)并不相同。比如,当我们想要在远程主机上执行 ls 命令时,我们并不需要写成”free_form=ls” ,这样写反而是错误的,因为并没有任何参数的名字是 free_form,当我们想要在远程主机中执行 ls 命令时,直接写成 ls 即可。因为 command 模块的作用是执行命令,所以,任何一个可以在远程主机上执行的命令都可以被称为 free_form
creates:与removes互斥且功能相反,指定一个文件路径或者目录路径,当该目录或文件存在时,则命令不执行
removes:与creates互斥功能相反,指定一个文件路径或者目录路径,当该目录或文件存在时,则命令执行,改参数不会删除文件;
stdin:标准输入
stdin_add_newline:给 stdin的值增加换行符;默认为YES,增加换行符;

范例:

#查看webservs组中的主机信息
ansible webservs --list-hosts

#查看远端passwd信息
ansible webservs -m command -a 'ls -l /etc/passwd'

#查看远端主机root下的信息chdir=/root(执行命令前先切换到root目录)
ansible webservs -m command -a 'chdir=/root ls -l'

#在远端主机上创建文件夹creates=/root/data(执行命令前先判断/root/data是否存在,存在则跳过,不存在则执行后续命令)
ansible webservs -m command -a 'creates=/root/data mkdir /root/data'

#尝试使用重定向(command模块不支持)
ansible webservs -m command -a 'echo hello > /data/hello.log'

#尝试使用变量(command模块不支持)
ansible webservs -m command -a 'echo $HOSTNAME'

shell模块(实用)

功能
  • 和command相似,用shell执行命令,支持各种符号,比如:*,$, >
  • 注意:此模块不具有幂等性
  • 该模块采用命令名称,后跟一个空格分隔参数列表
  • 自由格式的命令或参数是必需的
  • 它几乎与命令模块完全相同,但通过远程节点上的 shell () 运行命令:/bin/sh
  • 对于 Windows 目标,请改用win_shell模块
常用参数
chdir:运行命令前,切换到的目录
creates:与removes互斥且功能相反,指定一个文件路径或者目录路径,当该目录或文件存在时,则命令不执行
removes:与creates互斥功能相反,指定一个文件路径或者目录路径,当该目录或文件存在时,则命令执行
executable:更改用于执行该命令的shell,必须为绝对路径;

范例:

#获取远端主机的主机名称
[root@Ansible-Master ~11:03]#ansible webservs -m shell -a "echo $HOSTNAME"

#创建文件夹
[root@Ansible-Master ~11:06]#ansible webservs -m shell -a 'creates=/root/data mkdir /root/data'

#使用重定向
[root@Ansible-Master ~11:06]#ansible webservs -m shell -a 'echo hello > /root/data/hello.log'

Copy模块(实用)

功能
  • 从ansible服务器主控端复制文件到远程主机
  • 注意: src=file 如果是没指明路径,则为当前目录或当前目录下的files目录下的file文件
常用参数
backup:当设置backup=yes时创建一个包含时间戳信息的备份文件,该参数默认为NO
checksum:检查文件的哈希值,如果没有给出具体的值则使用src文件的本地计算校验和
decrypt:解密源文件,默认设置为yes
dest:目标路径
directory_mode:递归复制时,设置目录的权限;只对新创建的目录进行设置,对已经存在的目录不产生影响
follow:决定是否保留文件系统链接,默认设置为NO
force:影响是否必须始终替换远程文件。  如果为yes,当内容与源文件不同时,远程文件将被替换;如果为no,则只有在目标不存在的情况下才会传输文件
group:指定组
mode: 指定文件权限
owner: 指定拥有者
remote_src:指定目录是否在master主机,当这是为no时在master,yes时则为不在本段,2.8以上支持递归复制;
src:源目录

范例:

#要求:将ssh_key脚本复制到被控端组:webservs,且文件的拥有人:xiang、属组:bin、权限:700、名称:ssh-key.sh、若文件存在则生成备份
#在本端生成ssh_key.sh脚本文件
tee /root/Data/ssh_key.sh <<EOF
#!/bin/bash
PASS="redhat"
#设置网段最后的地址
END="130"
IP="$(ip a s ens36 | awk -F'[ /]+' 'NR==3{print $3}')"
NET=${IP%.*}.
rm -f /root/.ssh/id_rsa
[ -e ./SCANIP.log ] && rm -f SCANIP.log
for((i=120;i<="$END";i++));do
ping -c 1 -w 1  "${NET}$i" &> /dev/null  && echo "${NET}$i" >> SCANIP.log &
done
wait
ssh-keygen -P "" -f /root/.ssh/id_rsa
rpm -q sshpass || yum -y install sshpass
sshpass -p ${PASS} ssh-copy-id -o StrictHostKeyChecking=no "${IP}"
EOF
#调用copy文件将ssh_key.sh脚本文件拷贝到被控端组:Webservs
[root@Ansible-Master ~13:44]#ansible webservs -m copy -a 'src=/root/Date/ssh_key.sh dest=/root/data/ssh-key.sh owner=xiang group=bin  mode=700 backup=yes'
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "773ed6b1d312562033b0865926a56de91d7574b4", 
    "dest": "/root/data/ssh-key.sh", 
    "gid": 1, 
    "group": "bin", 
    "mode": "0700", 
    "owner": "xiang", 
    "path": "/root/data/ssh-key.sh", 
    "size": 867, 
    "state": "file", 
    "uid": 1001
}
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "773ed6b1d312562033b0865926a56de91d7574b4", 
    "dest": "/root/data/ssh-key.sh", 
    "gid": 1, 
    "group": "bin", 
    "mode": "0700", 
    "owner": "xiang", 
    "path": "/root/data/ssh-key.sh", 
    "size": 867, 
    "state": "file", 
    "uid": 1001
}

#指定内容,直接生成目标文件
ansible websrvs -m copy -a "content='test line1\ntest line2\n' dest=/tmp/test.txt"

##目录复制的区别
#复制/etc目录自身,注意/etc/后面没有/(这种方法性能会很差,不推荐使用,可以使用sync或者直接scp的方式实现)
ansible websrvs -m copy -a "src=/etc dest=/backup"
##复制/etc/下的文件,不包括/etc/目录自身,注意/etc/后面有/
ansible websrvs -m copy -a "src=/etc/ dest=/backup"

Script模块(实用)

功能
  • 在远程主机上运行ansible服务器上的脚本(无需执行权限)
  • 注意:此模块不具有幂等性
  • 注意:需标准输入脚本脚本无法执行,会一直等待输入
  • 该模块采用脚本名称,后跟一个空格分隔参数列表
  • 自由格式的命令或参数是必需的
  • 路径处的本地脚本将传输到远程节点,然后执行
  • 给定的脚本将通过远程节点上的 shell 环境进行处理
  • 这个模块不需要远程系统上的python,就像原始模块一样。
  • Windows 目标还支持此模块
常用参数
chdir:运行命令前,切换到的目录
creates:与removes互斥且功能相反,指定一个文件路径或者目录路径,当该目录或文件存在时,则命令不执行
removes:与creates互斥功能相反,指定一个文件路径或者目录路径,当该目录或文件存在时,则命令执行
executable:更改用于执行该命令的shell,必须为绝对路径;

范例:

##运行被控主机上的脚本文件
#在本段生成生成脚本test.sh
tee /root/test1.sh <<EOF
> #!/bin/bash
> hostname -I
> EOF
#ansible server端调用Script模块让脚本在远端运行
[root@Ansible-Master ~14:03]#ansible 192.168.213.122 -m script -a '/root/test1.sh'
192.168.213.122 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.213.122 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.213.122 closed."
    ], 
    "stdout": "192.168.40.182 192.168.0.122 192.168.213.122 192.168.122.1 240e:47c:3250:5398:8b92:72c6:58e7:7ed5 \r\n", 
    "stdout_lines": [
        "192.168.40.182 192.168.0.122 192.168.213.122 192.168.122.1 240e:47c:3250:5398:8b92:72c6:58e7:7ed5 "
    ]
}

Get_url模块

功能
  • 将文件从 HTTP、HTTPS 或 FTP 下载到远程服务器。远程服务器必须能够直接访问远程资源。
  • 默认情况下,如果在目标主机上设置了环境变量,则将通过该代理发送请求。可以通过为此任务设置变量或使用use_proxy选项来覆盖此行为
  • HTTP 重定向可以从 HTTP 重定向到 HTTPS,因此您应该确保两种协议的代理环境都是正确的。
  • 在 Ansible 2.4 中,当与 一起运行时,它将执行 HEAD 请求来验证 URL,但不会下载整个文件或根据哈希进行验证
  • 对于 Windows 目标,请改用win_get_url模块
常用参数
url: 下载文件的URL,支持HTTP,HTTPS或FTP协议
dest:下载到目标路径(绝对路径),如果目标是一个目录,就用服务器上面文件的名称,如果目标设置了名称就用目标设置的名称
owner:指定属主
group:指定属组
mode:指定权限
force: 如果yes,dest不是目录,将每次下载文件,如果内容改变,替换文件。如果否,则只有在目标不存在时才会下载该文件
checksum: 对目标文件在下载后计算摘要,以确保其完整性;示例: checksum="sha256:D98291AC[...]B6DC7B97",checksum="sha256:http://example/path/sha256sum.txt"
url_username: 用于HTTP基本认证的用户名。 对于允许空密码的站点,此参数可以不使用`url_password'
url_password: 用于HTTP基本认证的密码。 如果未指定`url_username'参数,则不会使用`url_password'参数
validate_certs:如果“no”,SSL证书将不会被验证。 适用于自签名证书在私有网站上使用
timeout: URL请求的超时时间,秒为单位

范例:

##下载nginx-1.18.0.tar.gz的安装包
#ansible server下载包,并生成MD5值以确保slave端下载的包的完整性;
wget http://nginx/download/nginx-1.18.0.tar.gz
#生成md5值
md5sum  nginx-1.18.0.tar.gz
openssl md5 nginx-1.18.0.tar.gz
#slave端下载nginx-1.18.0.tar.gz安装包
	ansible webservs -m get_url -a 'url=http://nginx/download/nginx-1.18.0.tar.gz dest=/data/nginx.tar.gz checksum="md5:b2d33d24d89b8b1f87ff5d251aa27eb8"'
#也可以不带md5值,但是建议带保证包的完整性
ansible webservs -m get_url -a 'url=http://nginx/download/nginx-1.18.0.tar.gz dest=/data/nginx.tar.gz‘

Fetch 模块

功能
  • 从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录;
  • 选项与copy类似
  • 无法抓取目录可以通过打包方式实现,譬如使用expect远程打包,或者使用ansible的Unarchivem模块
常用参数
fail_on_missing:当设置为YES时因为任何原因无法读取远程文件则任务失败;默认设置为NO
validate_checksum:获取文件后校验是否与源文件匹配
src:源路径
dest:目标路径

范例:

#拷贝slave端的messages文件至ansible 主端
[root@Ansible-Master ~22:35]#ansible webservs -m fetch -a 'src=/var/log/messages dest=/data/webservs_log owner=xiang mode=755'
192.168.213.123 | CHANGED => {
    "changed": true, 
    "checksum": "7d4cb6bd0a6ac7313ea127e55a678041fdd6948e", 
    "dest": "/data/webservs_log/192.168.213.123/var/log/messages", 
    "md5sum": "abfa071ca6e2b8cc2967dae30b2f5358", 
    "remote_checksum": "7d4cb6bd0a6ac7313ea127e55a678041fdd6948e", 
    "remote_md5sum": null
}
192.168.213.122 | CHANGED => {
    "changed": true, 
    "checksum": "3fd895c7c37e5314ab660b8113434d78a5231a9f", 
    "dest": "/data/webservs_log/192.168.213.122/var/log/messages", 
    "md5sum": "a678b4d0126d3cfe5e0652956a6e492b", 
    "remote_checksum": "3fd895c7c37e5314ab660b8113434d78a5231a9f", 
    "remote_md5sum": null
}
[root@Ansible-Master ~22:35]#tree /data/webservs_log/
/data/webservs_log/
├── 192.168.213.122
│   └── var
│       └── log
│           └── messages
└── 192.168.213.123
    └── var
        └── log
            └── messages

6 directories, 2 files

file模块(实用)

功能
  • 设置文件、符号链接或目录的属性。
  • 或者,删除文件、符号链接或目录。
  • 许多其他模块支持与模块相同的选项 - 包括复制、模板和程序集。
  • 对于 Windows 目标,请改用win_file模块
常用参数
path:文件路径
state:type设置(touch(创建)|directory(目录)|absent(删除))|link(软链接)
owner:拥有人
mode:权限
group:属组
recurse:YES|NO(是否递归)
force:当 state=link 时,可配合此参数强制创建链接文件,当 force=yes 时,表示强制创建链接文件,不过强制创建链接文件分为三种情况,情况一:当你要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当你要创建链接文件的目录中已经存在与链接文件同名的文件时,将 force 设置为 yes,会将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当你要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件
follow:决定是否保留文件系统链接,默认设置为NO
modification_time:修改文件修改时间

范例:

#创建目录/data/Test
[root@Ansible-Master ~22:36]#ansible webservs -m file -a 'path=/data/Test state=directory'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/data/Test", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/data/Test", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
#在/data目录下创建文件test
[root@Ansible-Master ~22:42]#ansible webservs -m file -a 'path=/data/test state=touch'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/test", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/test", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
#为test文件创建一个软链接到testlink,并修改test的属主和属组为xiang
[root@Ansible-Master ~22:45]#ansible webservs -m file -a 'src=/data/test path=/data/test-link state=link owner=xiang group=xiang'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/test-link", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 10, 
    "src": "/data/test", 
    "state": "link", 
    "uid": 0
}
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/test-link", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 10, 
    "src": "/data/test", 
    "state": "link", 
    "uid": 0
}
#递归修改/data目录下所有文件属主为bin
[root@Ansible-Master ~22:48]#ansible webservs -m file -a 'path=/data owner=bin recurse=yes'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "bin", 
    "path": "/data", 
    "size": 67, 
    "state": "directory", 
    "uid": 1
}
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "bin", 
    "path": "/data", 
    "size": 67, 
    "state": "directory", 
    "uid": 1
}
#删除data目录与目录下所有的文件
[root@Ansible-Master ~22:49]#ansible webservs -m file -a 'path=/data state=absent'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data", 
    "state": "absent"
}
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data", 
    "state": "absent"
}

stat模块

功能
  • 检查文件或文件系统的状态,类似于linux 的sata命令;注意:对于Windows目标,请改用win_stat模块
  • 对于 Windows 目标,请改用win_stat模块。
常用参数
path:文件/对象的完整路径(必须)
exists:判断是否存在
isuid:调用用户的ID与所有者ID是否匹配

范例:

#查看passwd文件的信息
[root@Ansible-Master ~22:57]#ansible localhost -m stat -a 'path=/etc/passwd'
localhost | SUCCESS => {
    "changed": false, 
    "stat": {
        "atime": 1652163001.6063051, 
        "attr_flags": "", 
        "attributes": [], 
        "block_size": 4096, 
        "blocks": 8, 
        "charset": "us-ascii", 
        "checksum": "d63ae556917e7d0a48c9c0c3bb2a6ed49ea7590a", 
        "ctime": 1652076520.7122421, 
        "dev": 64768, 
        "device_type": 0, 
        "executable": false, 
        "exists": true, 
        "gid": 0, 
        "gr_name": "root", 
        "inode": 34679716, 
        "isblk": false, 
        "ischr": false, 
        "isdir": false, 
        "isfifo": false, 
        "isgid": false, 
        "islnk": false, 
        "isreg": true, 
        "issock": false, 
        "isuid": false, 
        "mimetype": "text/plain", 
        "mode": "0644", 
        "mtime": 1652076520.7112422, 
        "nlink": 1, 
        "path": "/etc/passwd", 
        "pw_name": "root", 
        "readable": true, 
        "rgrp": true, 
        "roth": true, 
        "rusr": true, 
        "size": 3171, 
        "uid": 0, 
        "version": "372478715", 
        "wgrp": false, 
        "woth": false, 
        "writeable": true, 
        "wusr": true, 
        "xgrp": false, 
        "xoth": false, 
        "xusr": false
    }
}

Unarchive模块(常用)

功能
  • 解压缩与解包
  • 实现有两种用法:
    1. 将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes,此为默认值,可省略
    2. 将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
  • 该模块解压缩存档。它不会解压缩不包含存档的压缩文件。unarchive
  • 默认情况下,它会在解压缩之前将源文件从本地系统复制到目标。
  • 设置为解压缩目标上已存在的存档。remote_src=yes
  • 如果需要校验和验证,请改用 get_url 或 uri 来获取文件并设置 。remote_src=yes
  • 对于 Windows 目标,请改用win_unzip模块
常用参数
copy:默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no, 会在远程主机上寻找src源文件;
remote_src:和copy功能一样且互斥,当remote_src=no(默认)要将本地主机的存档文件,复制到目标主机的存档文件的本地路径下;当remote_src=yes时存档文件已在远程主机上,而存档文件不存在于本地主机,目标主机上要解压缩的现有存档文件的路径;
src:源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果 是远程主机上的路径,则需要设置copy=no;
dest:远程主机上的目标路径;
mode:设置解压缩后的文件权限;
list_files:如果设置list_files=True时列出压缩包中的所有文件,类似tar -tf,但有些不同,要先解压后才会返回值,限制:ansible版本必须2.0以上;
creates:指定一个文件名,当该文件存在时,则指令不执行;
keep_newer:当设置为keep_newer=no(默认)时,不替换比存档文件更新的现有文件;当设置为keep_newer=yes时,不替换当前已存在的文档,只覆盖不存在的文件或以时间更早的文件;

范例:

#将ansible主机上存在的nginx包传至slave上并解压缩,设置拥有人拥有组均为xiang
#copy=yes表示压缩包存在于asnible server端,且解压包本身不会传至对端;
[root@Ansible-Master ~13:28]#ansible 192.168.213.122 -m unarchive -a 'src=/root/nginx-1.18.0.tar.gz dest=/data  owner=xiang group=xiang mode=755 copy=yes'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/data", 
            "-z", 
            "--owner=xiang", 
            "--group=xiang", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1652246929.01-2830-57659039129653/source"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "0755", 
    "owner": "root", 
    "size": 26, 
    "src": "/root/.ansible/tmp/ansible-tmp-1652246929.01-2830-57659039129653/source", 
    "state": "directory", 
    "uid": 0
}

#列出nginx包类所有文件,并覆盖时间更旧的文件,其余文件不改变
#修改远端目录下的nginx文件;
[root@webservs1 /13:52]$ll -d /data/nginx-1.18.0/*
drwxr-xr-x 6 xiang xiang    326 May 11 13:48 /data/nginx-1.18.0/auto
-rw-r--r-- 1 xiang xiang 302863 Apr 21  2020 /data/nginx-1.18.0/CHANGES
-rw-r--r-- 1 xiang xiang 462213 Apr 21  2020 /data/nginx-1.18.0/CHANGES.ru
drwxr-xr-x 2 xiang xiang    168 May 11 13:49 /data/nginx-1.18.0/conf
-rwxr-xr-x 1 xiang xiang   2502 Apr 21  2020 /data/nginx-1.18.0/configure
drwxr-xr-x 4 xiang xiang     72 May 11 13:48 /data/nginx-1.18.0/contrib
drwxr-xr-x 2 xiang xiang     40 May 11 13:48 /data/nginx-1.18.0/html
-rw-r--r-- 1 xiang xiang   1397 Apr 21  2020 /data/nginx-1.18.0/LICENSE
drwxr-xr-x 2 xiang xiang     21 May 11 13:48 /data/nginx-1.18.0/man
-rw-r--r-- 1 xiang xiang     49 Apr 21  2020 /data/nginx-1.18.0/README
drwxr-xr-x 9 xiang xiang     91 May 11 13:48 /data/nginx-1.18.0/src
[root@webservs1 /13:52]$rm -rf /data/nginx-1.18.0/conf/
[root@webservs1 /13:52]$echo "1" >> /data/nginx-1.18.0/README 

#执行ansible命令,重新解压文件到/data目录进行修复
[root@Ansible-Master ~13:55]#ansible 192.168.213.122 -m unarchive -a 'src=/root/nginx-1.18.0.tar.gz dest=/data keep_newer=yes'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/data", 
            "-z", 
            "--keep-newer-files", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1652248674.7-3774-194026234272522/source"
        ], 
        "err": "/usr/bin/gtar: Current `nginx-1.18.0/configure' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/LICENSE' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/README' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/CHANGES.ru' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/CHANGES' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/man/nginx.8' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/html/50x.html' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/html/index.html' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_access_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_core_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_geo_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_geoip_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_handler.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_limit_conn_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_log_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_map_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_proxy_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_realip_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_return_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_script.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_script.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_split_clients_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_ssl_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_ssl_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_ssl_preread_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream_hash_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream_least_conn_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream_random_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream_round_robin.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream_round_robin.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_upstream_zone_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_variables.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_variables.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/stream/ngx_stream_write_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_alloc.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_alloc.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_atomic.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_channel.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_channel.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_daemon.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_darwin.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_darwin_config.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_darwin_init.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_darwin_sendfile_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_dlopen.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_dlopen.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_errno.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_errno.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_file_aio_read.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_files.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_files.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_freebsd.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_freebsd_config.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_linux.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_freebsd_init.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_freebsd_sendfile_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_gcc_atomic_amd64.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_gcc_atomic_ppc.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_gcc_atomic_sparc64.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_gcc_atomic_x86.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_linux_aio_read.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_linux_config.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_linux_init.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_linux_sendfile_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_os.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_posix_config.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_posix_init.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_process.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_process.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_process_cycle.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_process_cycle.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_readv_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_recv.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_send.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_setaffinity.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_setaffinity.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_setproctitle.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_setproctitle.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_shmem.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_shmem.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_socket.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_socket.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_solaris.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_solaris_config.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_solaris_init.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_solaris_sendfilev_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_sunpro_amd64.il' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_sunpro_atomic_sparc64.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_sunpro_sparc64.il' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_thread.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_sunpro_x86.il' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_thread_cond.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_thread_id.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_thread_mutex.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_time.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_time.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_udp_recv.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_udp_send.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_udp_sendmsg_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_user.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_user.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/os/unix/ngx_writev_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/misc/ngx_cpp_test_module.cpp' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/misc/ngx_google_perftools_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_auth_http_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_core_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_handler.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_imap_handler.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_imap_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_imap_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_parse.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_pop3_handler.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_pop3_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_pop3_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_proxy_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_smtp_handler.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_smtp_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_smtp_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_ssl_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/mail/ngx_mail_ssl_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_cache.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_config.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_copy_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_core_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_core_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_file_cache.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_header_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_parse.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_postpone_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_request.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_request.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_request_body.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_script.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_script.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_special_response.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_upstream.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_upstream.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_upstream_round_robin.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_upstream_round_robin.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_variables.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_variables.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/ngx_http_write_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2_encode.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2_huff_decode.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2_huff_encode.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/v2/ngx_http_v2_table.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_access_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_addition_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_auth_basic_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_auth_request_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_autoindex_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_browser_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_charset_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_chunked_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_dav_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_degradation_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_empty_gif_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_fastcgi_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_flv_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_geo_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_geoip_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_grpc_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_gunzip_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_gzip_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_gzip_static_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_headers_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_image_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_index_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_limit_conn_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_limit_req_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_log_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_map_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_memcached_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_mirror_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_mp4_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_not_modified_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_proxy_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_random_index_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_range_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_realip_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_referer_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_rewrite_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_scgi_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_secure_link_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_slice_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_split_clients_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_ssi_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_ssi_filter_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_ssl_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_ssl_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_static_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_stub_status_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_sub_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_try_files_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_upstream_hash_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_upstream_ip_hash_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_upstream_keepalive_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_upstream_random_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_upstream_least_conn_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_upstream_zone_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_userid_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_uwsgi_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/ngx_http_xslt_filter_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/perl/Makefile.PL' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/perl/nginx.pm' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/perl/nginx.xs' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/perl/ngx_http_perl_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/perl/ngx_http_perl_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/http/modules/perl/typemap' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_accept.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_connect.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_connect.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_openssl.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_openssl.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_openssl_stapling.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_pipe.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_pipe.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_posted.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_posted.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_timer.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_timer.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/ngx_event_udp.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_devpoll_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_epoll_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_eventport_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_kqueue_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_poll_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_select_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_win32_poll_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/event/modules/ngx_win32_select_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/nginx.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/nginx.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_array.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_array.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_buf.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_buf.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_conf_file.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_conf_file.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_config.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_connection.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_connection.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_core.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_cpuinfo.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_crc.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_crc32.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_crc32.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_crypt.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_crypt.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_cycle.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_cycle.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_file.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_file.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_hash.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_hash.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_inet.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_inet.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_list.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_list.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_log.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_log.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_md5.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_md5.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_module.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_module.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_murmurhash.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_murmurhash.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_open_file_cache.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_open_file_cache.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_output_chain.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_palloc.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_palloc.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_parse.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_parse.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_parse_time.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_queue.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_parse_time.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_proxy_protocol.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_proxy_protocol.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_queue.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_radix_tree.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_radix_tree.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_rbtree.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_rbtree.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_regex.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_regex.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_resolver.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_resolver.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_rwlock.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_rwlock.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_sha1.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_sha1.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_shmtx.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_shmtx.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_slab.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_slab.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_spinlock.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_string.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_string.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_syslog.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_syslog.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_thread_pool.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_thread_pool.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_times.c' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/src/core/ngx_times.h' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/README' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/geo2nginx.pl' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/vim/syntax/nginx.vim' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/vim/indent/nginx.vim' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/vim/ftplugin/nginx.vim' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/vim/ftdetect/nginx.vim' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/unicode2nginx/koi-utf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/unicode2nginx/unicode-to-nginx.pl' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/contrib/unicode2nginx/win-utf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/define' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/endianness' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/feature' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/have' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/have_headers' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/headers' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/include' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/init' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/install' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/make' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/module' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/modules' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/nohave' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/options' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/sources' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/stubs' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/summary' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/threads' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/unix' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/types/sizeof' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/types/typedef' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/types/uintptr_t' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/types/value' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/os/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/os/darwin' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/os/freebsd' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/os/linux' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/os/solaris' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/os/win32' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/make' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/zlib/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/zlib/make' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/zlib/makefile.bcc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/zlib/makefile.msvc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/zlib/makefile.owc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/perl/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/perl/make' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/pcre/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/pcre/make' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/pcre/makefile.bcc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/pcre/makefile.msvc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/pcre/makefile.owc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/openssl/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/openssl/make' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/openssl/makefile.bcc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/openssl/makefile.msvc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/libxslt/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/libgd/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/libatomic/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/libatomic/make' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/google-perftools/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/lib/geoip/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/acc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/bcc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/ccc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/clang' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/conf' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/gcc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/icc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/msvc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/name' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/owc' is newer or same age\n/usr/bin/gtar: Current `nginx-1.18.0/auto/cc/sunc' is newer or same age\n", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "0755", 
    "owner": "root", 
    "size": 26, 
    "src": "/root/.ansible/tmp/ansible-tmp-1652248674.7-3774-194026234272522/source", 
    "state": "directory", 
    "uid": 0
}

#检查
[root@webservs1 /13:52]$ll -d /data/nginx-1.18.0/*
drwxr-xr-x 6 xiang xiang    326 May 11 13:48 /data/nginx-1.18.0/auto
-rw-r--r-- 1 xiang xiang 302863 Apr 21  2020 /data/nginx-1.18.0/CHANGES
-rw-r--r-- 1 xiang xiang 462213 Apr 21  2020 /data/nginx-1.18.0/CHANGES.ru
drwxr-xr-x 2 xiang xiang    168 May 11 13:53 /data/nginx-1.18.0/conf
-rwxr-xr-x 1 xiang xiang   2502 Apr 21  2020 /data/nginx-1.18.0/configure
drwxr-xr-x 4 xiang xiang     72 May 11 13:48 /data/nginx-1.18.0/contrib
drwxr-xr-x 2 xiang xiang     40 May 11 13:48 /data/nginx-1.18.0/html
-rw-r--r-- 1 xiang xiang   1397 Apr 21  2020 /data/nginx-1.18.0/LICENSE
drwxr-xr-x 2 xiang xiang     21 May 11 13:48 /data/nginx-1.18.0/man
-rw-r--r-- 1 xiang xiang     51 May 11 13:52 /data/nginx-1.18.0/README
drwxr-xr-x 9 xiang xiang     91 May 11 13:48 /data/nginx-1.18.0/src

#若解压的目录存在则不执行
[root@Ansible-Master ~14:04]#ansible 192.168.213.122 -m unarchive -a 'src=/root/nginx-1.18.0.tar.gz dest=/data creates=/data/nginx-1.18.0'
192.168.213.122 | SKIPPED

Archive 模块

功能
  • 打包存档。
  • 它与取消存档相反。
  • 默认情况下,它假定目标上存在压缩源。
  • 在存档之前,它不会将源文件从本地系统复制到目标系统。
  • 存档后可以通过指定 remove=True 来删除源文件。
常用参数
attributes:
dest:目标存档的文件名称,一个目录或多个路径来引用多个文件时,这是必需的参数;
exclude_path:要从存档中排除的一个或多个文件的远程绝对路径、全局或路径或全局列表
force_archive:默认设置为no,当设置forece_archive=yes时允许您强制模块将此作为存档处理,即使只指定了单个文件。
path:需打包的文件路径
format:压缩包包类型;如:Choices:bz2、gz、tar、xz、zip
mode:权限
woner:拥有人
group:拥有组
remove:默认设置为NO,当设定remove=yes时删除源文件和目录结构,

范例:

#打包目录/var/log/,并排除掉其中的sa目录
[root@Ansible-Master data15:33]#ansible 192.168.213.122 -m archive -a 'path=/var/log/* dest=/data/log2.tar.bz2 exclude_path=/var/log/sa format=bz2'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "archived": [
        "/var/log/tallylog", 
        "/var/log/grubby_prune_debug", 
        "/var/log/lastlog", 
        "/var/log/wtmp", 
        "/var/log/btmp", 
        "/var/log/tuned/tuned.log", 
        "/var/log/audit/audit.log", 
        "/var/log/anaconda/anaconda.log", 
        "/var/log/anaconda/syslog", 
        "/var/log/anaconda/program.log", 
        "/var/log/anaconda/packaging.log", 
        "/var/log/anaconda/storage.log", 
        "/var/log/anaconda/ifcfg.log", 
        "/var/log/anaconda/ks-script-MGvAob.log", 
        "/var/log/anaconda/ks-script-kZXWLA.log", 
        "/var/log/anaconda/ks-script-xULLOt.log", 
        "/var/log/anaconda/journal.log", 
        "/var/log/boot.log", 
        "/var/log/vmware-vgauthsvc.log.0", 
        "/var/log/vmware-vmsvc.log", 
        "/var/log/cups/access_log", 
        "/var/log/cups/error_log", 
        "/var/log/cups/page_log", 
        "/var/log/dmesg.old", 
        "/var/log/boot.log-20220509", 
        "/var/log/maillog-20220510", 
        "/var/log/spooler", 
        "/var/log/boot.log-20220511", 
        "/var/log/dmesg", 
        "/var/log/cron", 
        "/var/log/messages", 
        "/var/log/vmware-network.8.log", 
        "/var/log/yum.log-20220503", 
        "/var/log/yum.log", 
        "/var/log/maillog", 
        "/var/log/secure", 
        "/var/log/nginx/error.log", 
        "/var/log/nginx/access.log", 
        "/var/log/boot.log-20220504", 
        "/var/log/boot.log-20220510", 
        "/var/log/messages-20220510", 
        "/var/log/vmware-network.7.log", 
        "/var/log/boot.log-20220505", 
        "/var/log/vmware-network.9.log", 
        "/var/log/spooler-20220510", 
        "/var/log/vmware-network.6.log", 
        "/var/log/vmware-network.5.log", 
        "/var/log/vmware-network.4.log", 
        "/var/log/vmware-network.3.log", 
        "/var/log/cron-20220510", 
        "/var/log/secure-20220510", 
        "/var/log/vmware-network.2.log", 
        "/var/log/vmware-network.1.log", 
        "/var/log/vmware-network.log", 
        "/var/log/boot.log-20220512"
    ], 
    "arcroot": "/var/log/", 
    "changed": true, 
    "dest": "/data/log2.tar.bz2", 
    "expanded_exclude_paths": [
        "/var/log/sa"
    ], 
    "expanded_paths": [
        "/var/log/tallylog", 
        "/var/log/grubby_prune_debug", 
        "/var/log/lastlog", 
        "/var/log/wtmp", 
        "/var/log/btmp", 
        "/var/log/httpd", 
        "/var/log/tuned", 
        "/var/log/audit", 
        "/var/log/chrony", 
        "/var/log/anaconda", 
        "/var/log/rhsm", 
        "/var/log/boot.log", 
        "/var/log/vmware-vgauthsvc.log.0", 
        "/var/log/vmware-vmsvc.log", 
        "/var/log/samba", 
        "/var/log/ppp", 
        "/var/log/glusterfs", 
        "/var/log/pluto", 
        "/var/log/ntpstats", 
        "/var/log/libvirt", 
        "/var/log/sssd", 
        "/var/log/swtpm", 
        "/var/log/cups", 
        "/var/log/speech-dispatcher", 
        "/var/log/gdm", 
        "/var/log/sa", 
        "/var/log/qemu-ga", 
        "/var/log/dmesg.old", 
        "/var/log/boot.log-20220509", 
        "/var/log/maillog-20220510", 
        "/var/log/spooler", 
        "/var/log/boot.log-20220511", 
        "/var/log/dmesg", 
        "/var/log/cron", 
        "/var/log/messages", 
        "/var/log/vmware-network.8.log", 
        "/var/log/yum.log-20220503", 
        "/var/log/yum.log", 
        "/var/log/maillog", 
        "/var/log/secure", 
        "/var/log/nginx", 
        "/var/log/boot.log-20220504", 
        "/var/log/boot.log-20220510", 
        "/var/log/messages-20220510", 
        "/var/log/vmware-network.7.log", 
        "/var/log/boot.log-20220505", 
        "/var/log/vmware-network.9.log", 
        "/var/log/spooler-20220510", 
        "/var/log/vmware-network.6.log", 
        "/var/log/vmware-network.5.log", 
        "/var/log/vmware-network.4.log", 
        "/var/log/vmware-network.3.log", 
        "/var/log/cron-20220510", 
        "/var/log/secure-20220510", 
        "/var/log/vmware-network.2.log", 
        "/var/log/vmware-network.1.log", 
        "/var/log/vmware-network.log", 
        "/var/log/boot.log-20220512"
    ], 
    "gid": 0, 
    "group": "root", 
    "missing": [
        "/var/log/sa"
    ], 
    "mode": "0644", 
    "owner": "root", 
    "size": 531626, 
    "state": "file", 
    "uid": 0
}
[root@webservs1 data07:33]$tar -tf log2.tar.bz2 
tallylog
grubby_prune_debug
lastlog
wtmp
btmp
tuned/tuned.log
audit/audit.log
anaconda/anaconda.log
anaconda/syslog
anaconda/program.log
anaconda/packaging.log
anaconda/storage.log
anaconda/ifcfg.log
anaconda/ks-script-MGvAob.log
anaconda/ks-script-kZXWLA.log
anaconda/ks-script-xULLOt.log
anaconda/journal.log
boot.log
vmware-vgauthsvc.log.0
vmware-vmsvc.log
samba/old/
pluto/peer/
libvirt/qemu/
swtpm/libvirt/
swtpm/libvirt/qemu/
cups/access_log
cups/error_log
cups/page_log
dmesg.old
boot.log-20220509
maillog-20220510
spooler
boot.log-20220511
dmesg
cron
messages
vmware-network.8.log
yum.log-20220503
yum.log
maillog
secure
nginx/error.log
nginx/access.log
boot.log-20220504
boot.log-20220510
messages-20220510
vmware-network.7.log
boot.log-20220505
vmware-network.9.log
spooler-20220510
vmware-network.6.log
vmware-network.5.log
vmware-network.4.log
vmware-network.3.log
cron-20220510
secure-20220510
vmware-network.2.log
vmware-network.1.log
vmware-network.log
boot.log-20220512

#打包目录/root/data/并修改权限为0600,拥有者为:xiang,属组为:xiang,打包类型为tar
[root@Ansible-Master data15:53]#ansible 192.168.213.122 -m archive -a 'path=/root/Date/ dest=/data/Date.tar format=bz2 owner=xiang mode=0600 group=xiang'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "archived": [], 
    "arcroot": "/root/Date/", 
    "changed": true, 
    "dest": "/data/Date.tar", 
    "expanded_exclude_paths": [], 
    "expanded_paths": [
        "/root/Date/"
    ], 
    "gid": 1001, 
    "group": "xiang", 
    "missing": [], 
    "mode": "0600", 
    "owner": "xiang", 
    "size": 46, 
    "state": "file", 
    "uid": 1001
}
[root@webservs1 ~15:58]$ll /data/Date.tar 
-rw------- 1 xiang xiang 46 May 12 07:53 /data/Date.tar

Hostname 模块

功能
  • 设置系统的主机名,支持大多数操作系统/发行版,包括使用 systemd 的操作系统/发行版。
  • 请注意,此模块不会修改 。您需要使用其他模块(如模板或替换)自行修改它。/etc/hosts
  • Windows、HP-UX 和 AIX 目前不受支持。
常用参数
name:你需要设置的主机名称
use:设置系统类型,如果不指定则会自动检测,但不要用于容器或者虚拟机;
	 支持系统:generic、debian、sles、redhat、alpine、systemd、openrc、openbsd、solaris、freebsd

范例:

#修改centos的主机名:
[root@Ansible-Master ~19:04]#ansible 192.168.213.124 -m hostname -a 'name=slave03 use=systemd'
192.168.213.124 | CHANGED => {
    "ansible_facts": {
        "ansible_domain": "", 
        "ansible_fqdn": "slave03", 
        "ansible_hostname": "slave03", 
        "ansible_nodename": "slave03", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "slave03"
}

Cron模块

功能
  • 使用此模块可以管理 crontab 和环境变量条目。此模块允许您创建环境变量并命名 crontab 条目、更新或删除它们。
  • 管理 crontab 作业时:模块包含一行与传递给模块的“名称”相对应的 crontab 条目的描述,将来的 ansible/模块调用使用它来查找/检查状态。“name”参数应该是唯一的,更改“name”值将导致创建新的 cron 任务(或删除其他任务)。"#Ansible: <name>"
  • 管理环境变量时,不添加注释行,但是当模块需要查找/检查状态时,它使用“name”参数来查找环境变量定义行。
  • 使用 % 等符号时,必须正确转义
常用参数
支持时间:minute,hour,day,month,weekday
Minute:分钟
Hour:小时
Day:天
Month:月
Weekday:周
Name:计划任务名称
Job:计划任务执行的内容
Disable:开启或关闭计划任务(yes|no)
backup:设置bakup=yes时,在修改已存在的计划任务前创建备份,默认设置为NO;
env:当设置env=yes时,可以新增环境变量,默认设置为NO
reboot:当设置为reboot=yes时会在重启后运行该计划任务,默认设置为no;
insertafter:需配合env=yes一起使用,将环境变量插入到指定环境变量的声明之后;
insertbefore:需配合env=yes一起使用,将环境变量插入到指定环境变量的声明之前;

范例:

#插入环境变量
[root@Ansible-Master Date20:22]#ansible 192.168.213.124 -m cron -a 'name="PATH" env=yes job=/opt/bin'
192.168.213.124 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [
        "PATH"
    ], 
    "jobs": [
        "backup mysql"
    ]
}

#在PATH变量后插入变量
[root@Ansible-Master Date20:22]#ansible 192.168.213.124 -m cron -a 'name="app_home" env=yes job=/srv/app insertafter=PATH'
192.168.213.124 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [
        "PATH", 
        "app_home"
    ], 
    "jobs": [
        "backup mysql"
    ]
}

#结果验证
[root@slave03 ~12:06]$crontab  -l
PATH="/opt/bin"
app_home="/srv/app"
#创建一个计划任务:周一到周五的2点30分执行脚本mysqk_backup.sh
[root@Ansible-Master ~19:34]#ansible 192.168.213.124 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'
192.168.213.124 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "backup mysql"
    ]
}
#结果验证
[root@slave03 ~12:05]$crontab  -l
#Ansible: backup mysql
30 2 * * 1-5 /root/mysql_backup.sh

#删除计划任务
[root@Ansible-Master Date20:30]#ansible 192.168.213.124 -m cron -a 'name="backup mysql" state=absent'
192.168.213.124 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [
        "PATH", 
        "app_home"
    ], 
    "jobs": []
}
#结果验证
[root@slave03 ~12:29]$crontab -l
PATH="/opt/bin"
app_home="/srv/app"
You have mail in /var/spool/mail/root
#禁用计划任务
[root@Ansible-Master Date20:28]#ansible 192.168.213.124 -m cron -a 'name="backup mysql" job=/root/mysql_backup.sh disabled=yes'
192.168.213.124 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [
        "PATH", 
        "app_home"
    ], 
    "jobs": [
        "backup mysql"
    ]
}
#结果验证
[root@slave03 ~12:24]$crontab -l
PATH="/opt/bin"
app_home="/srv/app"
#Ansible: backup mysql
#* * * * * /root/mysql_backup.sh

#启动计划任务
[root@Ansible-Master Date20:28]#ansible 192.168.213.124 -m cron -a 'name="backup mysql" job=/root/mysql_backup.sh disabled=no'
192.168.213.124 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [
        "PATH", 
        "app_home"
    ], 
    "jobs": [
        "backup mysql"
    ]
}
#结果验证
[root@slave03 ~12:24]$crontab -l
PATH="/opt/bin"
app_home="/srv/app"
Ansible: backup mysql
30 2 * * 1-5 /root/mysql_backup.sh

Yum模块和Apt模块

功能
  • yum 管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本
  • apt 模块管理 Debian 相关版本的软件包
  • 安装、升级、降级、删除以及使用 yum 包管理器列出包和组。此模块仅适用于 Python 2。如果您需要Python 3支持,请参阅dnf模块
常用参数
Name:包名称
State:服务状态(present,latest,absent)
exclude:排除
autoremove:自动删除,当设置autoremove=yes时,从系统中删除所有“叶”包;
allow_downgrade:降级,当设置allow_downgrade=yes时可以将包降为低版本;
disablerepo:禁止使用某个源镜像;
exclude:需要排除的包
enablerepo:启用仓库,当启用多个仓库时用“,”隔开
update_cache:默认为no,当设置update_cache=yes时强制更新yum缓存
download_only:只下载包,不安装;
download_dir:指定下载目录,必须没有安装过才会下载;

范例:

#查看ansible包的信息
[root@Ansible-Master ~11:35]#ansible 192.168.213.122 -m yum -a 'list=ansible'
192.168.213.122 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "results": [
        {
            "arch": "noarch", 
            "envra": "0:ansible-2.9.27-1.el7.noarch", 
            "epoch": "0", 
            "name": "ansible", 
            "release": "1.el7", 
            "repo": "EPEL", 
            "version": "2.9.27", 
            "yumstate": "available"
        }
    ]
}
#安装sos,但禁止从EPEL和base库中获取
[root@Ansible-Master ~11:37]#ansible 192.168.213.122 -m shell -a 'yum repolist'
[WARNING]: Consider using the yum module rather than running 'yum'.  If you need to use command because yum is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
192.168.213.122 | CHANGED | rc=0 >>
已加载插件:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
源标识                                   源名称                           状态
EPEL/7/x86_64                            EPEL                             13,755
base/7/x86_64                            base                             10,072
extras-1/7/x86_64                        extras-1                            509
repolist: 24,336

[root@Ansible-Master ~11:55]#ansible 192.168.213.122 -m yum -a 'name=sos disablerepo="EPEL"'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "sos"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package sos.noarch 0:3.9-2.el7.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package       Arch             Version                    Repository      Size\n================================================================================\nInstalling:\n sos           noarch           3.9-2.el7.centos           base           538 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package\n\nTotal download size: 538 k\nInstalled size: 1.8 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : sos-3.9-2.el7.centos.noarch                                  1/1 \n  Verifying  : sos-3.9-2.el7.centos.noarch                                  1/1 \n\nInstalled:\n  sos.noarch 0:3.9-2.el7.centos                                                 \n\nComplete!\n"
    ]
}


#指定源安装
ansible 192.168.213.122 -m yum -a "name=nginx state=present enablerepo=EPEL"
[root@Ansible-Master ~11:54]#ansible 192.168.213.122 -m yum -a "name=nginx state=present enablerepo=EPEL"
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "nginx"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package nginx.x86_64 1:1.20.1-9.el7 will be installed\n--> Processing Dependency: nginx-filesystem = 1:1.20.1-9.el7 for package: 1:nginx-1.20.1-9.el7.x86_64\n--> Processing Dependency: libcrypto.so.1.1(OPENSSL_1_1_0)(64bit) for package: 1:nginx-1.20.1-9.el7.x86_64\n--> Processing Dependency: libssl.so.1.1(OPENSSL_1_1_0)(64bit) for package: 1:nginx-1.20.1-9.el7.x86_64\n--> Processing Dependency: libssl.so.1.1(OPENSSL_1_1_1)(64bit) for package: 1:nginx-1.20.1-9.el7.x86_64\n--> Processing Dependency: nginx-filesystem for package: 1:nginx-1.20.1-9.el7.x86_64\n--> Processing Dependency: libcrypto.so.1.1()(64bit) for package: 1:nginx-1.20.1-9.el7.x86_64\n--> Processing Dependency: libssl.so.1.1()(64bit) for package: 1:nginx-1.20.1-9.el7.x86_64\n--> Running transaction check\n---> Package nginx-filesystem.noarch 1:1.20.1-9.el7 will be installed\n---> Package openssl11-libs.x86_64 1:1.1.1k-3.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package                 Arch          Version                Repository   Size\n================================================================================\nInstalling:\n nginx                   x86_64        1:1.20.1-9.el7         EPEL        587 k\nInstalling for dependencies:\n nginx-filesystem        noarch        1:1.20.1-9.el7         EPEL         24 k\n openssl11-libs          x86_64        1:1.1.1k-3.el7         EPEL        1.5 M\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+2 Dependent packages)\n\nTotal download size: 2.1 M\nInstalled size: 5.2 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                              136 kB/s | 2.1 MB  00:15     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : 1:nginx-filesystem-1.20.1-9.el7.noarch                       1/3 \n  Installing : 1:openssl11-libs-1.1.1k-3.el7.x86_64                         2/3 \n  Installing : 1:nginx-1.20.1-9.el7.x86_64                                  3/3 \n  Verifying  : 1:openssl11-libs-1.1.1k-3.el7.x86_64                         1/3 \n  Verifying  : 1:nginx-filesystem-1.20.1-9.el7.noarch                       2/3 \n  Verifying  : 1:nginx-1.20.1-9.el7.x86_64                                  3/3 \n\nInstalled:\n  nginx.x86_64 1:1.20.1-9.el7                                                   \n\nDependency Installed:\n  nginx-filesystem.noarch 1:1.20.1-9.el7  openssl11-libs.x86_64 1:1.1.1k-3.el7 \n\nComplete!\n"
    ]
}
#通过yum模块下载sl包且不安装,存放到指定目录/data/package下
[root@Ansible-Master ~11:43]#ansible 192.168.213.122 -m yum -a 'name=sl download_dir=/data/package download_only=yes'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "sl"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package sl.x86_64 0:5.02-1.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package       Arch              Version                  Repository       Size\n================================================================================\nInstalling:\n sl            x86_64            5.02-1.el7               EPEL             14 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package\n\nTotal download size: 14 k\nInstalled size: 17 k\nBackground downloading packages, then exiting:\nexiting because \"Download Only\" specified\n"
    ]
}
#结果验证
[root@slave1 ~11:41]$ls /data/package/
sl-5.02-1.el7.x86_64.rpm
#安装httpd包
ansible 192.168.213.122 -m yum -a 'name=httpd state=present re'
[root@Ansible-Master ~11:52]#ansible 192.168.213.122 -m yum -a 'name=httpd state=present'
192.168.213.122 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "httpd-2.4.6-93.el7.centos.x86_64 providing httpd is already installed"
    ]
}

#卸载httpd
root@Ansible-Master ~11:52]#ansible 192.168.213.122 -m yum -a 'name=httpd state=absent'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "removed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "已加载插件:fastestmirror, langpacks\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-93.el7.centos 将被 删除\n--> 正在处理依赖关系 httpd-mmn = 20120211x8664,它被软件包 mod_fcgid-2.3.9-6.el7.x86_64 需要\n--> 正在处理依赖关系 httpd-mmn = 20120211x8664,它被软件包 1:mod_ssl-2.4.6-93.el7.centos.x86_64 需要\n--> 正在处理依赖关系 httpd,它被软件包 1:mod_ssl-2.4.6-93.el7.centos.x86_64 需要\n--> 正在处理依赖关系 httpd = 2.4.6-93.el7.centos,它被软件包 1:mod_ssl-2.4.6-93.el7.centos.x86_64 需要\n--> 正在处理依赖关系 httpd = 2.4.6-93.el7.centos,它被软件包 httpd-manual-2.4.6-93.el7.centos.noarch 需要\n--> 正在检查事务\n---> 软件包 httpd-manual.noarch.0.2.4.6-93.el7.centos 将被 删除\n---> 软件包 mod_fcgid.x86_64.0.2.3.9-6.el7 将被 删除\n---> 软件包 mod_ssl.x86_64.1.2.4.6-93.el7.centos 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package           架构        版本                        源              大小\n================================================================================\n正在删除:\n httpd             x86_64      2.4.6-93.el7.centos         @anaconda      9.4 M\n为依赖而移除:\n httpd-manual      noarch      2.4.6-93.el7.centos         @anaconda      5.5 M\n mod_fcgid         x86_64      2.3.9-6.el7                 @anaconda      228 k\n mod_ssl           x86_64      1:2.4.6-93.el7.centos       @anaconda      224 k\n\n事务概要\n================================================================================\n移除  1 软件包 (+3 依赖软件包)\n\n安装大小:15 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  正在删除    : 1:mod_ssl-2.4.6-93.el7.centos.x86_64                        1/4 \n  正在删除    : httpd-manual-2.4.6-93.el7.centos.noarch                     2/4 \n  正在删除    : mod_fcgid-2.3.9-6.el7.x86_64                                3/4 \n  正在删除    : httpd-2.4.6-93.el7.centos.x86_64                            4/4 \n  验证中      : mod_fcgid-2.3.9-6.el7.x86_64                                1/4 \n  验证中      : httpd-manual-2.4.6-93.el7.centos.noarch                     2/4 \n  验证中      : 1:mod_ssl-2.4.6-93.el7.centos.x86_64                        3/4 \n  验证中      : httpd-2.4.6-93.el7.centos.x86_64                            4/4 \n\n删除:\n  httpd.x86_64 0:2.4.6-93.el7.centos                                            \n\n作为依赖被删除:\n  httpd-manual.noarch 0:2.4.6-93.el7.centos    mod_fcgid.x86_64 0:2.3.9-6.el7   \n  mod_ssl.x86_64 1:2.4.6-93.el7.centos        \n\n完毕!\n"
    ]
}

Service模块(常用)

功能
  • 控制远程主机上的服务。支持的初始化系统包括:BSD init, OpenRC, SysV, Solaris SMF, systemd, upstart.
  • 针对winodws系统请使用win_service模块
常用参数
Name:服务名称
State:服务状态:(reloaded, restarted, started, stopped)
Enabled:是否开机自启动(yes|no)
pattern:指定启动关键字符,并执行更改为对应状态
sleep:指定服务休眠与启动之间的间隔,常用于自动化脚本

范例:

#基于可运行的进程/usr/sbin/httpd,启动服务httpd
[root@Ansible-Master ~14:02]#ansible 192.168.213.122 -m service -a 'name=httpd pattern=/usr/sbin/httpd state=started'
[WARNING]: Ignoring "pattern" as it is not used in "systemd"
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "httpd", 
    "state": "started", 
    "status": {
        "ActiveEnterTimestampMonotonic": "0", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "inactive", 
        "After": "basic.target system.slice nss-lookup.target network.target remote-fs.target -.mount systemd-journald.socket tmp.mount", 
        "AllowIsolate": "no", 
        "AmbientCapabilities": "0", 
        "AssertResult": "no", 
        "AssertTimestampMonotonic": "0", 
        "Before": "shutdown.target", 
        "BlockIOAccounting": "no", 
        "BlockIOWeight": "18446744073709551615", 
        "CPUAccounting": "no", 
        "CPUQuotaPerSecUSec": "infinity", 
        "CPUSchedulingPolicy": "0", 
        "CPUSchedulingPriority": "0", 
        "CPUSchedulingResetOnFork": "no", 
        "CPUShares": "18446744073709551615", 
        "CanIsolate": "no", 
        "CanReload": "yes", 
        "CanStart": "yes", 
        "CanStop": "yes", 
        "CapabilityBoundingSet": "18446744073709551615", 
        "ConditionResult": "no", 
        "ConditionTimestampMonotonic": "0", 
        "Conflicts": "shutdown.target", 
        "ControlPID": "0", 
        "DefaultDependencies": "yes", 
        "Delegate": "no", 
        "Description": "The Apache HTTP Server", 
        "DevicePolicy": "auto", 
        "Documentation": "man:httpd(8) man:apachectl(8)", 
        "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
        "ExecMainCode": "0", 
        "ExecMainExitTimestampMonotonic": "0", 
        "ExecMainPID": "0", 
        "ExecMainStartTimestampMonotonic": "0", 
        "ExecMainStatus": "0", 
        "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "FailureAction": "none", 
        "FileDescriptorStoreMax": "0", 
        "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
        "GuessMainPID": "yes", 
        "IOScheduling": "0", 
        "Id": "httpd.service", 
        "IgnoreOnIsolate": "no", 
        "IgnoreOnSnapshot": "no", 
        "IgnoreSIGPIPE": "yes", 
        "InactiveEnterTimestampMonotonic": "0", 
        "InactiveExitTimestampMonotonic": "0", 
        "JobTimeoutAction": "none", 
        "JobTimeoutUSec": "0", 
        "KillMode": "control-group", 
        "KillSignal": "18", 
        "LimitAS": "18446744073709551615", 
        "LimitCORE": "18446744073709551615", 
        "LimitCPU": "18446744073709551615", 
        "LimitDATA": "18446744073709551615", 
        "LimitFSIZE": "18446744073709551615", 
        "LimitLOCKS": "18446744073709551615", 
        "LimitMEMLOCK": "65536", 
        "LimitMSGQUEUE": "819200", 
        "LimitNICE": "0", 
        "LimitNOFILE": "4096", 
        "LimitNPROC": "7155", 
        "LimitRSS": "18446744073709551615", 
        "LimitRTPRIO": "0", 
        "LimitRTTIME": "18446744073709551615", 
        "LimitSIGPENDING": "7155", 
        "LimitSTACK": "18446744073709551615", 
        "LoadState": "loaded", 
        "MainPID": "0", 
        "MemoryAccounting": "no", 
        "MemoryCurrent": "18446744073709551615", 
        "MemoryLimit": "18446744073709551615", 
        "MountFlags": "0", 
        "Names": "httpd.service", 
        "NeedDaemonReload": "no", 
        "Nice": "0", 
        "NoNewPrivileges": "no", 
        "NonBlocking": "no", 
        "NotifyAccess": "main", 
        "OOMScoreAdjust": "0", 
        "OnFailureJobMode": "replace", 
        "PermissionsStartOnly": "no", 
        "PrivateDevices": "no", 
        "PrivateNetwork": "no", 
        "PrivateTmp": "yes", 
        "ProtectHome": "no", 
        "ProtectSystem": "no", 
        "RefuseManualStart": "no", 
        "RefuseManualStop": "no", 
        "RemainAfterExit": "no", 
        "Requires": "-.mount basic.target system.slice", 
        "RequiresMountsFor": "/var/tmp", 
        "Restart": "no", 
        "RestartUSec": "100ms", 
        "Result": "success", 
        "RootDirectoryStartOnly": "no", 
        "RuntimeDirectoryMode": "0755", 
        "SameProcessGroup": "no", 
        "SecureBits": "0", 
        "SendSIGHUP": "no", 
        "SendSIGKILL": "yes", 
        "Slice": "system.slice", 
        "StandardError": "inherit", 
        "StandardInput": "null", 
        "StandardOutput": "journal", 
        "StartLimitAction": "none", 
        "StartLimitBurst": "5", 
        "StartLimitInterval": "10000000", 
        "StartupBlockIOWeight": "18446744073709551615", 
        "StartupCPUShares": "18446744073709551615", 
        "StatusErrno": "0", 
        "StopWhenUnneeded": "no", 
        "SubState": "dead", 
        "SyslogLevelPrefix": "yes", 
        "SyslogPriority": "30", 
        "SystemCallErrorNumber": "0", 
        "TTYReset": "no", 
        "TTYVHangup": "no", 
        "TTYVTDisallocate": "no", 
        "TasksAccounting": "no", 
        "TasksCurrent": "18446744073709551615", 
        "TasksMax": "18446744073709551615", 
        "TimeoutStartUSec": "1min 30s", 
        "TimeoutStopUSec": "1min 30s", 
        "TimerSlackNSec": "50000", 
        "Transient": "no", 
        "Type": "notify", 
        "UMask": "0022", 
        "UnitFilePreset": "disabled", 
        "UnitFileState": "disabled", 
        "WatchdogTimestampMonotonic": "0", 
        "WatchdogUSec": "0"
    }
}

#重新加载httpd服务
[root@Ansible-Master ~14:03]#ansible 192.168.213.122 -m service -a 'name=httpd state=reloaded'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "httpd", 
    "state": "started", 
    "status": {
        "ActiveEnterTimestampMonotonic": "0", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "inactive", 
        "After": "-.mount basic.target nss-lookup.target remote-fs.target network.target systemd-journald.socket tmp.mount system.slice", 
        "AllowIsolate": "no", 
        "AmbientCapabilities": "0", 
        "AssertResult": "no", 
        "AssertTimestampMonotonic": "0", 
        "Before": "shutdown.target", 
        "BlockIOAccounting": "no", 
        "BlockIOWeight": "18446744073709551615", 
        "CPUAccounting": "no", 
        "CPUQuotaPerSecUSec": "infinity", 
        "CPUSchedulingPolicy": "0", 
        "CPUSchedulingPriority": "0", 
        "CPUSchedulingResetOnFork": "no", 
        "CPUShares": "18446744073709551615", 
        "CanIsolate": "no", 
        "CanReload": "yes", 
        "CanStart": "yes", 
        "CanStop": "yes", 
        "CapabilityBoundingSet": "18446744073709551615", 
        "ConditionResult": "no", 
        "ConditionTimestampMonotonic": "0", 
        "Conflicts": "shutdown.target", 
        "ControlPID": "0", 
        "DefaultDependencies": "yes", 
        "Delegate": "no", 
        "Description": "The Apache HTTP Server", 
        "DevicePolicy": "auto", 
        "Documentation": "man:httpd(8) man:apachectl(8)", 
        "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
        "ExecMainCode": "0", 
        "ExecMainExitTimestampMonotonic": "0", 
        "ExecMainPID": "0", 
        "ExecMainStartTimestampMonotonic": "0", 
        "ExecMainStatus": "0", 
        "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "FailureAction": "none", 
        "FileDescriptorStoreMax": "0", 
        "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
        "GuessMainPID": "yes", 
        "IOScheduling": "0", 
        "Id": "httpd.service", 
        "IgnoreOnIsolate": "no", 
        "IgnoreOnSnapshot": "no", 
        "IgnoreSIGPIPE": "yes", 
        "InactiveEnterTimestampMonotonic": "0", 
        "InactiveExitTimestampMonotonic": "0", 
        "JobTimeoutAction": "none", 
        "JobTimeoutUSec": "0", 
        "KillMode": "control-group", 
        "KillSignal": "18", 
        "LimitAS": "18446744073709551615", 
        "LimitCORE": "18446744073709551615", 
        "LimitCPU": "18446744073709551615", 
        "LimitDATA": "18446744073709551615", 
        "LimitFSIZE": "18446744073709551615", 
        "LimitLOCKS": "18446744073709551615", 
        "LimitMEMLOCK": "65536", 
        "LimitMSGQUEUE": "819200", 
        "LimitNICE": "0", 
        "LimitNOFILE": "4096", 
        "LimitNPROC": "7155", 
        "LimitRSS": "18446744073709551615", 
        "LimitRTPRIO": "0", 
        "LimitRTTIME": "18446744073709551615", 
        "LimitSIGPENDING": "7155", 
        "LimitSTACK": "18446744073709551615", 
        "LoadState": "loaded", 
        "MainPID": "0", 
        "MemoryAccounting": "no", 
        "MemoryCurrent": "18446744073709551615", 
        "MemoryLimit": "18446744073709551615", 
        "MountFlags": "0", 
        "Names": "httpd.service", 
        "NeedDaemonReload": "no", 
        "Nice": "0", 
        "NoNewPrivileges": "no", 
        "NonBlocking": "no", 
        "NotifyAccess": "main", 
        "OOMScoreAdjust": "0", 
        "OnFailureJobMode": "replace", 
        "PermissionsStartOnly": "no", 
        "PrivateDevices": "no", 
        "PrivateNetwork": "no", 
        "PrivateTmp": "yes", 
        "ProtectHome": "no", 
        "ProtectSystem": "no", 
        "RefuseManualStart": "no", 
        "RefuseManualStop": "no", 
        "RemainAfterExit": "no", 
        "Requires": "-.mount basic.target system.slice", 
        "RequiresMountsFor": "/var/tmp", 
        "Restart": "no", 
        "RestartUSec": "100ms", 
        "Result": "success", 
        "RootDirectoryStartOnly": "no", 
        "RuntimeDirectoryMode": "0755", 
        "SameProcessGroup": "no", 
        "SecureBits": "0", 
        "SendSIGHUP": "no", 
        "SendSIGKILL": "yes", 
        "Slice": "system.slice", 
        "StandardError": "inherit", 
        "StandardInput": "null", 
        "StandardOutput": "journal", 
        "StartLimitAction": "none", 
        "StartLimitBurst": "5", 
        "StartLimitInterval": "10000000", 
        "StartupBlockIOWeight": "18446744073709551615", 
        "StartupCPUShares": "18446744073709551615", 
        "StatusErrno": "0", 
        "StopWhenUnneeded": "no", 
        "SubState": "dead", 
        "SyslogLevelPrefix": "yes", 
        "SyslogPriority": "30", 
        "SystemCallErrorNumber": "0", 
        "TTYReset": "no", 
        "TTYVHangup": "no", 
        "TTYVTDisallocate": "no", 
        "TasksAccounting": "no", 
        "TasksCurrent": "18446744073709551615", 
        "TasksMax": "18446744073709551615", 
        "TimeoutStartUSec": "1min 30s", 
        "TimeoutStopUSec": "1min 30s", 
        "TimerSlackNSec": "50000", 
        "Transient": "no", 
        "Type": "notify", 
        "UMask": "0022", 
        "UnitFilePreset": "disabled", 
        "UnitFileState": "disabled", 
        "WatchdogTimestampMonotonic": "0", 
        "WatchdogUSec": "0"
    }
}

#重启httpd服务
[root@Ansible-Master ~14:10]#ansible 192.168.213.122 -m service -a 'name=httpd state=restarted'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "httpd", 
    "state": "started", 
    "status": {
        "ActiveEnterTimestamp": "一 2022-05-16 13:55:52 GMT", 
        "ActiveEnterTimestampMonotonic": "11892335196", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "active", 
        "After": "-.mount tmp.mount nss-lookup.target network.target system.slice systemd-journald.socket remote-fs.target basic.target", 
        "AllowIsolate": "no", 
        "AmbientCapabilities": "0", 
        "AssertResult": "yes", 
        "AssertTimestamp": "一 2022-05-16 13:55:40 GMT", 
        "AssertTimestampMonotonic": "11880275057", 
        "Before": "shutdown.target", 
        "BlockIOAccounting": "no", 
        "BlockIOWeight": "18446744073709551615", 
        "CPUAccounting": "no", 
        "CPUQuotaPerSecUSec": "infinity", 
        "CPUSchedulingPolicy": "0", 
        "CPUSchedulingPriority": "0", 
        "CPUSchedulingResetOnFork": "no", 
        "CPUShares": "18446744073709551615", 
        "CanIsolate": "no", 
        "CanReload": "yes", 
        "CanStart": "yes", 
        "CanStop": "yes", 
        "CapabilityBoundingSet": "18446744073709551615", 
        "ConditionResult": "yes", 
        "ConditionTimestamp": "一 2022-05-16 13:55:40 GMT", 
        "ConditionTimestampMonotonic": "11880275057", 
        "Conflicts": "shutdown.target", 
        "ControlGroup": "/system.slice/httpd.service", 
        "ControlPID": "0", 
        "DefaultDependencies": "yes", 
        "Delegate": "no", 
        "Description": "The Apache HTTP Server", 
        "DevicePolicy": "auto", 
        "Documentation": "man:httpd(8) man:apachectl(8)", 
        "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
        "ExecMainCode": "0", 
        "ExecMainExitTimestampMonotonic": "0", 
        "ExecMainPID": "7926", 
        "ExecMainStartTimestamp": "一 2022-05-16 13:55:40 GMT", 
        "ExecMainStartTimestampMonotonic": "11880275595", 
        "ExecMainStatus": "0", 
        "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[一 2022-05-16 13:55:40 GMT] ; stop_time=[n/a] ; pid=7926 ; code=(null) ; status=0/0 }", 
        "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "FailureAction": "none", 
        "FileDescriptorStoreMax": "0", 
        "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
        "GuessMainPID": "yes", 
        "IOScheduling": "0", 
        "Id": "httpd.service", 
        "IgnoreOnIsolate": "no", 
        "IgnoreOnSnapshot": "no", 
        "IgnoreSIGPIPE": "yes", 
        "InactiveEnterTimestampMonotonic": "0", 
        "InactiveExitTimestamp": "一 2022-05-16 13:55:40 GMT", 
        "InactiveExitTimestampMonotonic": "11880275633", 
        "JobTimeoutAction": "none", 
        "JobTimeoutUSec": "0", 
        "KillMode": "control-group", 
        "KillSignal": "18", 
        "LimitAS": "18446744073709551615", 
        "LimitCORE": "18446744073709551615", 
        "LimitCPU": "18446744073709551615", 
        "LimitDATA": "18446744073709551615", 
        "LimitFSIZE": "18446744073709551615", 
        "LimitLOCKS": "18446744073709551615", 
        "LimitMEMLOCK": "65536", 
        "LimitMSGQUEUE": "819200", 
        "LimitNICE": "0", 
        "LimitNOFILE": "4096", 
        "LimitNPROC": "7155", 
        "LimitRSS": "18446744073709551615", 
        "LimitRTPRIO": "0", 
        "LimitRTTIME": "18446744073709551615", 
        "LimitSIGPENDING": "7155", 
        "LimitSTACK": "18446744073709551615", 
        "LoadState": "loaded", 
        "MainPID": "7926", 
        "MemoryAccounting": "no", 
        "MemoryCurrent": "18446744073709551615", 
        "MemoryLimit": "18446744073709551615", 
        "MountFlags": "0", 
        "Names": "httpd.service", 
        "NeedDaemonReload": "no", 
        "Nice": "0", 
        "NoNewPrivileges": "no", 
        "NonBlocking": "no", 
        "NotifyAccess": "main", 
        "OOMScoreAdjust": "0", 
        "OnFailureJobMode": "replace", 
        "PermissionsStartOnly": "no", 
        "PrivateDevices": "no", 
        "PrivateNetwork": "no", 
        "PrivateTmp": "yes", 
        "ProtectHome": "no", 
        "ProtectSystem": "no", 
        "RefuseManualStart": "no", 
        "RefuseManualStop": "no", 
        "RemainAfterExit": "no", 
        "Requires": "-.mount basic.target system.slice", 
        "RequiresMountsFor": "/var/tmp", 
        "Restart": "no", 
        "RestartUSec": "100ms", 
        "Result": "success", 
        "RootDirectoryStartOnly": "no", 
        "RuntimeDirectoryMode": "0755", 
        "SameProcessGroup": "no", 
        "SecureBits": "0", 
        "SendSIGHUP": "no", 
        "SendSIGKILL": "yes", 
        "Slice": "system.slice", 
        "StandardError": "inherit", 
        "StandardInput": "null", 
        "StandardOutput": "journal", 
        "StartLimitAction": "none", 
        "StartLimitBurst": "5", 
        "StartLimitInterval": "10000000", 
        "StartupBlockIOWeight": "18446744073709551615", 
        "StartupCPUShares": "18446744073709551615", 
        "StatusErrno": "0", 
        "StatusText": "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec", 
        "StopWhenUnneeded": "no", 
        "SubState": "running", 
        "SyslogLevelPrefix": "yes", 
        "SyslogPriority": "30", 
        "SystemCallErrorNumber": "0", 
        "TTYReset": "no", 
        "TTYVHangup": "no", 
        "TTYVTDisallocate": "no", 
        "TasksAccounting": "no", 
        "TasksCurrent": "6", 
        "TasksMax": "18446744073709551615", 
        "TimeoutStartUSec": "1min 30s", 
        "TimeoutStopUSec": "1min 30s", 
        "TimerSlackNSec": "50000", 
        "Transient": "no", 
        "Type": "notify", 
        "UMask": "0022", 
        "UnitFilePreset": "disabled", 
        "UnitFileState": "disabled", 
        "WatchdogTimestamp": "一 2022-05-16 13:55:52 GMT", 
        "WatchdogTimestampMonotonic": "11892335169", 
        "WatchdogUSec": "0"
    }
}


#关闭httpd服务
[root@Ansible-Master ~14:11]#ansible 192.168.213.122 -m service -a 'name=httpd state=stopped'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "httpd", 
    "state": "stopped", 
    "status": {
        "ActiveEnterTimestamp": "一 2022-05-16 13:56:48 GMT", 
        "ActiveEnterTimestampMonotonic": "11947982662", 
        "ActiveExitTimestamp": "一 2022-05-16 13:56:35 GMT", 
        "ActiveExitTimestampMonotonic": "11934899645", 
        "ActiveState": "active", 
        "After": "-.mount tmp.mount nss-lookup.target network.target system.slice systemd-journald.socket remote-fs.target basic.target", 
        "AllowIsolate": "no", 
        "AmbientCapabilities": "0", 
        "AssertResult": "yes", 
        "AssertTimestamp": "一 2022-05-16 13:56:36 GMT", 
        "AssertTimestampMonotonic": "11935923508", 
        "Before": "shutdown.target", 
        "BlockIOAccounting": "no", 
        "BlockIOWeight": "18446744073709551615", 
        "CPUAccounting": "no", 
        "CPUQuotaPerSecUSec": "infinity", 
        "CPUSchedulingPolicy": "0", 
        "CPUSchedulingPriority": "0", 
        "CPUSchedulingResetOnFork": "no", 
        "CPUShares": "18446744073709551615", 
        "CanIsolate": "no", 
        "CanReload": "yes", 
        "CanStart": "yes", 
        "CanStop": "yes", 
        "CapabilityBoundingSet": "18446744073709551615", 
        "ConditionResult": "yes", 
        "ConditionTimestamp": "一 2022-05-16 13:56:36 GMT", 
        "ConditionTimestampMonotonic": "11935923508", 
        "Conflicts": "shutdown.target", 
        "ControlGroup": "/system.slice/httpd.service", 
        "ControlPID": "0", 
        "DefaultDependencies": "yes", 
        "Delegate": "no", 
        "Description": "The Apache HTTP Server", 
        "DevicePolicy": "auto", 
        "Documentation": "man:httpd(8) man:apachectl(8)", 
        "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
        "ExecMainCode": "0", 
        "ExecMainExitTimestampMonotonic": "0", 
        "ExecMainPID": "8057", 
        "ExecMainStartTimestamp": "一 2022-05-16 13:56:36 GMT", 
        "ExecMainStartTimestampMonotonic": "11935924017", 
        "ExecMainStatus": "0", 
        "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[一 2022-05-16 13:56:36 GMT] ; stop_time=[n/a] ; pid=8057 ; code=(null) ; status=0/0 }", 
        "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[一 2022-05-16 13:56:35 GMT] ; stop_time=[一 2022-05-16 13:56:35 GMT] ; pid=8052 ; code=exited ; status=0 }", 
        "FailureAction": "none", 
        "FileDescriptorStoreMax": "0", 
        "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
        "GuessMainPID": "yes", 
        "IOScheduling": "0", 
        "Id": "httpd.service", 
        "IgnoreOnIsolate": "no", 
        "IgnoreOnSnapshot": "no", 
        "IgnoreSIGPIPE": "yes", 
        "InactiveEnterTimestamp": "一 2022-05-16 13:56:36 GMT", 
        "InactiveEnterTimestampMonotonic": "11935923013", 
        "InactiveExitTimestamp": "一 2022-05-16 13:56:36 GMT", 
        "InactiveExitTimestampMonotonic": "11935924040", 
        "JobTimeoutAction": "none", 
        "JobTimeoutUSec": "0", 
        "KillMode": "control-group", 
        "KillSignal": "18", 
        "LimitAS": "18446744073709551615", 
        "LimitCORE": "18446744073709551615", 
        "LimitCPU": "18446744073709551615", 
        "LimitDATA": "18446744073709551615", 
        "LimitFSIZE": "18446744073709551615", 
        "LimitLOCKS": "18446744073709551615", 
        "LimitMEMLOCK": "65536", 
        "LimitMSGQUEUE": "819200", 
        "LimitNICE": "0", 
        "LimitNOFILE": "4096", 
        "LimitNPROC": "7155", 
        "LimitRSS": "18446744073709551615", 
        "LimitRTPRIO": "0", 
        "LimitRTTIME": "18446744073709551615", 
        "LimitSIGPENDING": "7155", 
        "LimitSTACK": "18446744073709551615", 
        "LoadState": "loaded", 
        "MainPID": "8057", 
        "MemoryAccounting": "no", 
        "MemoryCurrent": "18446744073709551615", 
        "MemoryLimit": "18446744073709551615", 
        "MountFlags": "0", 
        "Names": "httpd.service", 
        "NeedDaemonReload": "no", 
        "Nice": "0", 
        "NoNewPrivileges": "no", 
        "NonBlocking": "no", 
        "NotifyAccess": "main", 
        "OOMScoreAdjust": "0", 
        "OnFailureJobMode": "replace", 
        "PermissionsStartOnly": "no", 
        "PrivateDevices": "no", 
        "PrivateNetwork": "no", 
        "PrivateTmp": "yes", 
        "ProtectHome": "no", 
        "ProtectSystem": "no", 
        "RefuseManualStart": "no", 
        "RefuseManualStop": "no", 
        "RemainAfterExit": "no", 
        "Requires": "-.mount basic.target system.slice", 
        "RequiresMountsFor": "/var/tmp", 
        "Restart": "no", 
        "RestartUSec": "100ms", 
        "Result": "success", 
        "RootDirectoryStartOnly": "no", 
        "RuntimeDirectoryMode": "0755", 
        "SameProcessGroup": "no", 
        "SecureBits": "0", 
        "SendSIGHUP": "no", 
        "SendSIGKILL": "yes", 
        "Slice": "system.slice", 
        "StandardError": "inherit", 
        "StandardInput": "null", 
        "StandardOutput": "journal", 
        "StartLimitAction": "none", 
        "StartLimitBurst": "5", 
        "StartLimitInterval": "10000000", 
        "StartupBlockIOWeight": "18446744073709551615", 
        "StartupCPUShares": "18446744073709551615", 
        "StatusErrno": "0", 
        "StatusText": "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec", 
        "StopWhenUnneeded": "no", 
        "SubState": "running", 
        "SyslogLevelPrefix": "yes", 
        "SyslogPriority": "30", 
        "SystemCallErrorNumber": "0", 
        "TTYReset": "no", 
        "TTYVHangup": "no", 
        "TTYVTDisallocate": "no", 
        "TasksAccounting": "no", 
        "TasksCurrent": "6", 
        "TasksMax": "18446744073709551615", 
        "TimeoutStartUSec": "1min 30s", 
        "TimeoutStopUSec": "1min 30s", 
        "TimerSlackNSec": "50000", 
        "Transient": "no", 
        "Type": "notify", 
        "UMask": "0022", 
        "UnitFilePreset": "disabled", 
        "UnitFileState": "disabled", 
        "WatchdogTimestamp": "一 2022-05-16 13:56:48 GMT", 
        "WatchdogTimestampMonotonic": "11947982635", 
        "WatchdogUSec": "0"
    }
}

User模块(常用)

功能
  • 管理用户帐户和用户属性。
  • 对于 Windows 目标,请改用win_user模块
常用参数
`Name`:用于指定操作的 user,必须项。
`Uid`:用于指定 user 的 UID,默认为空。
`non_unique`:与uid参数一起使用,允许改变UID为非唯一值。
`Group`:参数用于指定用户 主组。默认值为空,为空时创建的用户组名跟用户名一致。
`Groups`:参数用于指定用户属组,可以在创建用户时指定用户属组,也可以管理已经存在的用户属组。Append跟groups参数一起使用管理用户属组,默认为false,如果 append='yes' ,则从groups参数中增加用户的属组;如果append='no' ,则用户属组只设置为groups中的组,移除其他所有属组。
`State`:参数用于指定用户是否存在于远程主机中。可选值有 present、absent,默认值为 present。
`Remove`:参数在 state=absent 时使用,等价于 userdel --remove 布尔类型,默认值为 no。当remove=yes时将删除与该用户关联的所有目录;
`Home`:参数用于指定用户home目录,值为路径
`create_home`:在用户创建时或home目录不存在时为用户创建home目录,布尔类型,默认值为 true
`move_home`:如果设置为yes,结合home= 使用,临时迁移用户家目录到特定目录
`Comment`:参数用于指定用户注释信息
`Shell`:参数用于指定用户默认shell
`System`:参数用于指定用户是否是系统用户
`Expires`:参数用于指定用户过期时间,相当于设置 /etc/shadow 文件中的的 第8列
`Passwd`:参数用于指定用户密码,但是这个密码不能是明文密码,而是一个对明文密码加密后的字符串,默认为空
`password_lock`:参数用于锁定指定用户,布尔类型,默认为空
`update_password`:	参数可选值有always 和 on_create,默认为always;
当设置为always时,password参数的值与 /etc/shadow 中密码字符串不一致时更新用户的密码;
当设置为on_create时,password参数的值与 /etc/shadow 中密码字符串不一致时也不会更新用户的密码,但如果是新创建的用户,则此参数即使为on_create,也会更新用户密码。
`generate_ssh_key`: 参数用于指定是否生成ssh密钥对,布尔类型,默认为false。当设置为yes时,为用户生成 ssh 密钥对,默认在 ~/.ssh 目录中生成名为 id_rsa私钥 和 id_rsa.pub公钥,如果同名密钥已经存在,则不做任何操作。
`sssh_key_bits`:当 generate_ssh_key=yes 时,指定生成的ssh key加密位数。
`ssh_key_file`:当 generate_ssh_key=yes 时,使用此参数指定ssh私钥的路径及名称,会在同路径下生成以私钥名开头以 .pub 结尾对应公钥。
`ssh_key_comment`:当 generate_ssh_key=yes 时,在创建证书时,使用此参数设置公钥中的注释信息。如果同名密钥已经存在,则不做任何操作。当不指定此参数时,默认注释信息为"ansible-generated on $hostname”。
`ssh_key_passphrase`:当 generate_ssh_key=yes 时,在创建证书时,使用此参数设置私钥密码。如果同名密钥已经存在,则不做任何操作。
`ssh_key_type`:当 generate_ssh_key=yes 时,在创建证书时,使用此参数指定密钥对的类型。默认值为 rsa,如果同名密钥已经存在,则不做任何操作。
`Append`:跟groups参数一起使用管理用户属组,默认为no,如果 append='yes' ,则从groups参数中增加用户的属组;如果 append='no' ,则用户属组只设置为groups中的组,移除其他所有属组。

范例

#创建用户user1,备注"test user"并设置组为root,UID为2048;
ansible webservs -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root' 
[root@Ansible-Master ~14:15]#ansible webservs -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "test user", 
    "create_home": true, 
    "group": 0, 
    "home": "/app/user1", 
    "name": "user1", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 2048
}
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "test user", 
    "create_home": true, 
    "group": 0, 
    "home": "/app/user1", 
    "name": "user1", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 2048
}


#删除用户user1
[root@Ansible-Master ~14:14]#ansible webservs -m user -a 'name=user1 state=absent remove=yes' 
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "user1", 
    "remove": true, 
    "state": "absent"
}
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "user1", 
    "remove": true, 
    "state": "absent"
}
#创建一个用户nignx,并完成以下要求:
#1.UID为88
#2.组为niginx,附加组为root和daemon
#3.shell类型为/sbin/nologin
#4.家目录为/data/nginx但不创建
#5.UID为非唯一
#6.指定为系统用户
ansible webservs  -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx  non_unique=yes append=yes'
[root@Ansible-Master ~14:30]#ansible webservs  -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx  non_unique=yes append=yes'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "nginx", 
    "create_home": false, 
    "group": 1002, 
    "groups": "root,daemon", 
    "home": "/data/nginx", 
    "name": "nginx", 
    "shell": "/sbin/nologin", 
    "state": "present", 
    "system": true, 
    "uid": 88
}
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "nginx", 
    "create_home": false, 
    "group": 1002, 
    "groups": "root,daemon", 
    "home": "/data/nginx", 
    "name": "nginx", 
    "shell": "/sbin/nologin", 
    "state": "present", 
    "system": true, 
    "uid": 88
}
#生成二进制密码
ansible localhost -m debug -a "msg={{ 'psxiang' |password_hash('sha512','salt')}}"
[root@Ansible-Master ~14:30]#ansible localhost -m debug -a "msg={{ 'psxiang' |password_hash('sha512','salt')}}"
localhost | SUCCESS => {
    "msg": "$6$salt$sOQuidJn3wMaCZrp7JicbnPa/PiOYuKOj9R4gx22UjqhdeMTx4OJMjKI355t2QaPGzO1cKRGd6zmRoVtF3lHJ."
}

#使用二进制密码创建用户test1:
ansible webservs -m user -a 'name=test1 password="$6$salt$sOQuidJn3wMaCZrp7JicbnPa/PiOYuKOj9R4gx22UjqhdeMTx4OJMjKI355t2QaPGzO1cKRGd6zmRoVtF3lHJ."'
[root@Ansible-Master ~14:36]#ansible webservs -m user -a 'name=test1 password="$6$salt$sOQuidJn3wMaCZrp7JicbnPa/PiOYuKOj9R4gx22UjqhdeMTx4OJMjKI355t2QaPGzO1cKRGd6zmRoVtF3lHJ."'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 2049, 
    "home": "/home/test1", 
    "name": "test1", 
    "password": "NOT_LOGGING_PASSWORD", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 2049
}
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 2049, 
    "home": "/home/test1", 
    "name": "test1", 
    "password": "NOT_LOGGING_PASSWORD", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 2049
}
#登陆验证
[root@slave2 ~06:37]$su - xiang
Last login: Mon May  9 06:20:34 GMT 2022 from 192.168.213.101 on pts/1
[xiang@slave2 ~]$ 
[xiang@slave2 ~]$ 
[xiang@slave2 ~]$ su - test1
Password: 
Last login: Thu May 19 06:37:09 GMT 2022 on pts/0
[test1@slave2 ~]$ 
#为test1用户生成ssh密码,并存放到/root/.ssh/id_rsa:
ansible webservs -m user -a 'name=test1 generate_ssh_key=yes ssh_key_bits=4096 ssh_key_file=.ssh/id_rsa'
[root@Ansible-Master ~14:40]#ansible webservs -m user -a 'name=test1 generate_ssh_key=yes ssh_key_bits=4096 ssh_key_file=/root/ssh/id_rsa'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "append": false, 
    "changed": true, 
    "comment": "", 
    "group": 2049, 
    "home": "/home/test1", 
    "move_home": false, 
    "name": "test1", 
    "shell": "/bin/bash", 
    "ssh_fingerprint": "4096 SHA256:USbSj/r06NaNRqmbK0pOILgcSQMz1hMoTVjyrvDoaC0 ansible-generated on slave1 (RSA)", 
    "ssh_key_file": "/root/ssh/id_rsa", 
    "ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC1YkSkGGQtKSDb70JJ94tvyX1myGDtYWBU6oeh/zJr5YEVEInD03yrOWKOiIDsh+jqkV72io7QMpb06Nq4U4M7FRKRLew1wK3YAWoEr/7gY+ujGOB8N1T3W6Z4UzYMGft1RdoF3dOlqADZ41aS9NXGO1zU5MTu1IsnrZMjY9foaNPrsEMxy4zPHDZ5Uz+Q48+GN0sqfZzKWocHlmaaq2kkkoVzLhVYmwtbd+eooE6mGX+me+9FLUgJXzbN8nrFPqrb9r5kHcIZJcbtvYAwlPW1BMKZwu7bo0Q7MsT4kWYkAEzkPJ3Gwvo9oWTPSiernC/h+p8yBFHIy78OdgTaSyt/1q5xDLXQ7WiCemDkKRJlqm6RvHmE3qYqr8pWqfB9EpEw0ZEgP4pJBMT4Bu3kmEheXbydDmsi7vcTmdqT5MQzFPDWoXmFivR3YCYrc3PlKAeAC9YIkvyy90oG1FmqqhzRP0po8SOSOtd+goFgedMsLPKdIfxiWIm6bW0r0jbFd+Sdkn8T59j15KKX9qNIdPBS37T0GF+kotoS4QOSzuIDF10NUw6yxI3aK6bgIot5YoXUU1l52Cr8NN1B5/V9SAagaI60FH2Df1AvQKYIhzCa4Gto45hdDCWW1VKudq1jjClRFEg3lx896/mnM7POUTXHQB84MmxdR084Nx/t0fLLGQ== ansible-generated on slave1", 
    "state": "present", 
    "uid": 2049
}
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "append": false, 
    "changed": true, 
    "comment": "", 
    "group": 2049, 
    "home": "/home/test1", 
    "move_home": false, 
    "name": "test1", 
    "shell": "/bin/bash", 
    "ssh_fingerprint": "4096 SHA256:lb6ONG/vV+OvmXlHwDiial2Kufc31c6N3UmMNrHOX54 ansible-generated on slave2 (RSA)", 
    "ssh_key_file": "/root/ssh/id_rsa", 
    "ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDV+L2EsENSm/jpX0s/3RCPMiLCFsiK5fSp/ZtWmQSr9VZwav3hsyigctXQpUPryXeUBSDOFUkDDSrgdHZ0oIjuM+RVZYKTzFzDcnhgY/e8l0ycp0I1WXxp9O8wGYP6OCjPLXenYMcSnP/lBuLY5T/XaCADDjuQLuehQKJ7DTdyRMgpGRf7vkr3D8YJ+dEMNUlyaF8Kp3AaZzp4GR8YJWBaUNtS9/EufDZxqAVfNc6b1JmHs5JZw83KUI12WeSznRwAcZzB4Ehg0dzPSXVzCL4UpeC2MUsbTzVHEoILu26nRBhw/NqtArC4YxYWU8+L8gBGxHkG5Pak0mLLBQy7nq4wpOzulgnGL7H5Z96g1S4IoZVAiaCs8DsP/A/Tff3dc3B9ZLYOnePFYaiyKHzAg2O5sCrljyRDRKqivB7pT/nVCdDXeQZiGg5bqcHUNQqxJu88pQjjf7kVoAGJY8fNivkJOGxllm5vGVKSgonbOeW8sTqPmDHOhYJ0o+azZ7CiizUqEJ1xjSuf7LQQ5dAwfQaomx7caIoVZFDh5VFr9KmNLAye++UugouUzXrl1BEG5+//GFn4O23rpT7MgZebhCnTezXG3BCfz8PTveNyPCMYRo6iaQ8QbB3tIIqTyWkfclMfWdUuQcc/+h24nlncnw88mb4Npfxzd3Zc2eROk7yXjQ== ansible-generated on slave2", 
    "state": "present", 
    "uid": 2049
}
#验证
[root@slave2 ssh06:44]$ls /root/ssh/
id_rsa  id_rsa.pub

group模块(常用)

功能
  • 管理用户帐户和用户属性。
  • 对于 Windows 目标,请改用win_user模块
常用参数
`name`:必须参数,用于指定要操作的组名称。
`state`:用于指定组的状态,两个值可选,present,absent,默认为 present,设置为absent 表示删除组。
`gid`:用于指定组的gid
`System`:YES|NO,是否为系统组
`non_unique`:允许gid为非唯一值

范例

#创建一个Test组,组ID为188,指定为系统组
[root@Ansible-Master ~14:44]#ansible webservs -m group -a 'name=Test gid=188 system=yes'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 188, 
    "name": "Test", 
    "state": "present", 
    "system": true
}
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 188, 
    "name": "Test", 
    "state": "present", 
    "system": true
}

#删除Test组
[root@Ansible-Master ~14:51]#ansible webservs -m group -a 'name=Test state=absent'
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "Test", 
    "state": "absent"
}
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "Test", 
    "state": "absent"
}

Lineinfile 模块

功能
  • 功能:相当于sed,可以批量的进行文本替换;
  • 说明
ansible在使用sed进行替换时,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换时,存在问题,无法正常进行替换。其实在ansible自身提供了两个模块:lineinfile模块和replace模块,可以方便的进行替换一般在ansible当中去修改某个文件的单行进行替换的时候需要使用lineinfile模块 regexp参数:使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最 后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。如果想进行多行匹配进行替换需要使用replace模块;
常用参数
`Path`:文件路径
`Regexp`:匹配项
`Line`:输出项
`create`:默认值为no;配合state=present使用,如果指定create=yes,若文件不存在则会创建该文件;若为no则会失败;
`backup`:在修改文件前创建一个包含时间戳信息的备份文件,这样如果您不正确地修改了原始文件,就可以重新获得原始文件。  
`insertafter`:将line的值插入到指定的行后,默认插入到最后一次匹配项;如果需要插入到第一次匹配项,则需配合设置(firstmatch=yes);若将正则表达式同时传递给regexp和insertafter,则只有在没有找到regexp匹配的情况下才会执行insertafter(`将会将匹配行后向替换为line的值`)。
`insertbefore`:将line的值插入到指定的行前,默认插入到最后一次匹配项;如果需要插入到第一次匹配项,则需配合设置(firstmatch=yes);若将正则表达式同时传递给regexp和insertafter,则只有在没有找到regexp匹配的情况下才会执行insertafter(`将会将匹配行后向替换为line的值`)。
`mode`:需改对应文件的权限
`others`:file模块可以使用的参数也可以在这里使用
`owner`:修改对应文件的拥有人

范例

#删除sudoers文件中以%wheel开头的行
[root@Ansible-Master ~15:04]#ansible 192.168.213.123 -m lineinfile -a "path=/etc/sudoers state=absent regexp='^%wheel'"
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup": "", 
    "changed": true, 
    "found": 2, 
    "msg": "2 line(s) removed"
}
#关闭selinx
[root@Ansible-Master ~15:29]#ansible webservs -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled'"
192.168.213.122 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup": "", 
    "changed": true, 
    "msg": "line replaced"
}
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup": "", 
    "changed": true, 
    "msg": "line replaced"
}
#修改hosts文件,并修改其拥有人拥有组为root,权限为0644
[root@Ansible-Master ~15:37]#ansible 192.168.213.123 -m file -a 'path=/root/data/hosts owner=xiang group=xiang mode=755'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 1001, 
    "group": "xiang", 
    "mode": "0755", 
    "owner": "xiang", 
    "path": "/root/data/hosts", 
    "size": 99, 
    "state": "file", 
    "uid": 1001
}
[root@Ansible-Master ~15:37]#ansible 192.168.213.123 -m lineinfile -a "path=/root/data/hosts regexp='127\.0\.0\.1' line='127.0.0.1 localhost' owner=root group=root mode=0644"
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup": "", 
    "changed": true, 
    "msg": "ownership, perms or SE linux context changed"
}
#验证
[root@slave2 ssh07:38]$cat /root/data/hosts 
127.0.0.1 localhost
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
[root@slave2 ssh07:38]$cat /etc/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
[root@slave2 ssh07:38]$ll /root/data/hosts 
-rw-r--r-- 1 root root 99 May 19 07:37 /root/data/hosts
#在httpd.conf文件中#Listen后插入Listen 8888的条目
[root@slave2 data07:47]$grep "Listen" /root/data/httpd.conf 
# Listen: Allows you to bind Apache to specific IP addresses and/or
# Change this to Listen on specific IP addresses as shown below to 
#Listen 12.34.56.78:80
Listen 80
[root@Ansible-Master ~15:48]#ansible 192.168.213.123 -m lineinfile -a "path=/root/data/httpd.conf insertafter='^#Listen' line='Listen 8888'"
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup": "", 
    "changed": true, 
    "msg": "line added"
}
#验证
[root@slave2 data07:47]$grep "Listen" /root/data/httpd.conf 
# Listen: Allows you to bind Apache to specific IP addresses and/or
# Change this to Listen on specific IP addresses as shown below to 
#Listen 12.34.56.78:80
Listen 8888
Listen 80

##在httpd.conf文件中Listen后插入Listen 9999的条目
[root@Ansible-Master ~15:54]#ansible 192.168.213.123 -m lineinfile -a "path=/root/data/httpd.conf insertafter='^Listen' line='Listen 9999' firstmatch=yes"
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup": "", 
    "changed": true, 
    "msg": "line added"
}
#验证
[root@slave2 data07:53]$grep "Listen" /root/data/httpd.conf 
# Listen: Allows you to bind Apache to specific IP addresses and/or
# Change this to Listen on specific IP addresses as shown below to 
#Listen 12.34.56.78:80
Listen 8888
Listen 9999
Listen 80

Replace模块

功能
  • 类似sed的替换功能,这个模块将替换文件中一个模式的所有实例。
  • 用户需不会替换文件中一个模式的所有值来确保幂等性
常用参数
`Path`:文件路径
`Regexp`:匹配项
`replace`:替换结果
`encoding`:读取文件时使用的字符集,默认值为utf-8
`mode`:需改对应文件的权限
`others`:file模块可以使用的参数也可以在这里使用
`owner`:修改对应文件的拥有人
`backup`:在修改文件前创建一个包含时间戳信息的备份文件,这样如果您不正确地修改了原始文件,就可以重新获得原始文件。  
`after`:指定匹配内容,只有被匹配后的内容才会被替换,可以与befoce配合使用
`befoce`:如果指定,只有匹配之前的内容将被替换/删除,可以与after配合使用

范例

#修改fstab文件,在所有uuid开头的行前添加注释
[root@Ansible-Master ~16:30]#ansible 192.168.213.123 -m replace -a "path=/root/data/fstab regexp='^(UUID.*)' replace='#\1'"
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "msg": "4 replacements made"
}
#验证
[root@slave2 data08:29]$cat fstab 

#
# /etc/fstab
# Created by anaconda on Sat Mar 12 16:41:11 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=367417a1-2c26-4275-871e-75e9814ac18b /                       xfs     defaults        0 0
UUID=6c54b2f7-1570-419b-8ddc-d4d21f4b9fd0 /boot                   xfs     defaults        0 0
UUID=f3a36a62-a0a0-4bd5-b046-7c89f191f303 /home                   xfs     defaults        0 0
UUID=e1abe904-4cbe-4d3c-8765-23cd2626b007 swap                    swap    defaults        0 0
[root@slave2 data08:29]$cat fstab 

#
# /etc/fstab
# Created by anaconda on Sat Mar 12 16:41:11 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
#UUID=367417a1-2c26-4275-871e-75e9814ac18b /                       xfs     defaults        0 0
#UUID=6c54b2f7-1570-419b-8ddc-d4d21f4b9fd0 /boot                   xfs     defaults        0 0
#UUID=f3a36a62-a0a0-4bd5-b046-7c89f191f303 /home                   xfs     defaults        0 0
#UUID=e1abe904-4cbe-4d3c-8765-23cd2626b007 swap                    swap    defaults        0 0
#修改1.txt,将<<Directory "/var/WWW">与</Directory>之间的值注释
#原文件
[root@slave2 data08:45]$cat 1.txt 
<Directory />
    AllowOverride none
    Require all denied
</Directory>


 Note that from this point forward you must specifically allow
 particular features to be enabled - so if something's not working as
 you might expect, make sure that you have specifically enabled it
 below.



 DocumentRoot: The directory out of which you will serve your
 documents. By default, all requests are taken from this directory, but
 symbolic links and aliases may be used to point to other locations.

DocumentRoot "/var/www/html"


 Relax access to content within /var/www.

<Directory "/var/www">
     AllowOverride None
     # Allow open access:
     Require all granted
</Directory>

[root@Ansible-Master ~16:47]#ansible 192.168.213.123 -m replace -a "path=/root/data/1.txt after='<Directory \"/var/www\">' before='</Directory>' regexp='^(.+)$' replace='# \1'"
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "msg": "3 replacements made"
}

#验证
[root@slave2 data08:47]$cat 1.txt 
<Directory />
    AllowOverride none
    Require all denied
</Directory>


 Note that from this point forward you must specifically allow
 particular features to be enabled - so if something's not working as
 you might expect, make sure that you have specifically enabled it
 below.



 DocumentRoot: The directory out of which you will serve your
 documents. By default, all requests are taken from this directory, but
 symbolic links and aliases may be used to point to other locations.

DocumentRoot "/var/www/html"


 Relax access to content within /var/www.

<Directory "/var/www">
#      AllowOverride None
#      # Allow open access:
#      Require all granted
</Directory>

Mount模块

功能
  • 将活动中的设备挂载到系统上,并写入/etc/fstab
常用参数
`path`:挂载点
`src`:需要挂载的设备
`Fstype`:挂载设备的文件系统;Iso9660(光驱)、ext4、xfs、nfs、cifs(samba的共享文件系统
)ntfs(windows磁盘文件系统)
`Opts`:挂载属性
`state`:挂载动作:(mounted:挂载设备,并将配置写入/etc/fstab;Unmounted:卸载设备,不会清除/etc/fstab写入的配置;Absent:卸载设备,并清理/etc/fstab写入的配置,remounted:重新挂载)

范例:

#临时挂载cdrom
[root@Ansible-Master ~17:21]#ansible 192.168.213.123 -m mount -a 'src=/dev/cdrom path=/mnt/cdrom fstype=iso9660 state=present'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dump": "0", 
    "fstab": "/etc/fstab", 
    "fstype": "iso9660", 
    "name": "/mnt/cdrom", 
    "opts": "defaults", 
    "passno": "0", 
    "src": "/dev/cdrom"
}

#验证
[root@slave2 data09:23]$df -h |grep "/dev/sr0"
/dev/sr0        4.5G  4.5G     0 100% /mnt/cdrom
#卸载cdrom
[root@Ansible-Master ~17:35]#ansible 192.168.213.123 -m mount -a 'path=/mnt/cdrom fstype=iso9660 state=unmounted'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dump": "0", 
    "fstab": "/etc/fstab", 
    "fstype": "iso9660", 
    "name": "/mnt/cdrom", 
    "opts": "defaults", 
    "passno": "0"
}
#永久挂载cdrom
[root@Ansible-Master ~17:21]#ansible 192.168.213.123 -m mount -a 'src=/dev/cdrom path=/mnt/cdrom fstype=iso9660 state=mounted'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dump": "0", 
    "fstab": "/etc/fstab", 
    "fstype": "iso9660", 
    "name": "/mnt/cdrom", 
    "opts": "defaults", 
    "passno": "0", 
    "src": "/dev/cdrom"
}
#永久卸载
[root@Ansible-Master ~18:01]#ansible 192.168.213.123 -m mount -a 'src=/dev/cdrom path=/mnt/cdrom fstype=iso9660 state=absent'
192.168.213.123 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dump": "0", 
    "fstab": "/etc/fstab", 
    "fstype": "iso9660", 
    "name": "/mnt/cdrom", 
    "opts": "defaults", 
    "passno": "0", 
    "src": "/dev/cdrom"
}

setup模块

功能
  • ansible-playbook会自动调用这个模块,除非将gather_facts设置为no;用于收集系统参数信息
  • window也可以使用该模块
常用参数
`filter`:检索关键词,并返回josn格式的值;
`gather_timeout`:收集的超时时间,默认为10S;

范例

#查看所有信息
ansible all -m setup
#查看节点名称
ansible all -m setup -a "filter=ansible_nodename" 
#查看主机名
ansible all -m setup -a "filter=ansible_hostname"
#查看节点所属domin
ansible all -m setup -a "filter=ansible_domain"
#查看总内存
ansible all -m setup -a "filter=ansible_memtotal_mb"
#查看内存使用情况
ansible all -m setup -a "filter=ansible_memory_mb"
#查看空闲内存
ansible all -m setup -a "filter=ansible_memfree_mb"
#查看系统所属的OS系列
ansible all -m setup -a "filter=ansible_os_family"
#查看系统的主版本号
ansible all -m setup -a "filter=ansible_distribution_major_version"
#查看系统详细版本号
ansible all -m setup -a "filter=ansible_distribution_version"
#查看节点CPU数量
ansible all -m setup -a "filter=ansible_processor_vcpus"
#查看节点所有IP信息
ansible all -m setup -a "filter=ansible_all_ipv4_addresses"
#查看节点软件架构
ansible all -m setup -a "filter=ansible_architecture"
#查看线程
ansible all -m setup -a "filter=ansible_processor*"
ansible all -m setup -a 'filter=ansible_env'
#查看内存
[root@Ansible-Master ~19:14]#ansible 192.168.213.123 -m setup -a "filter=ansible_memtotal_mb"
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "ansible_memtotal_mb": 1819, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
#查看系统所属系列簇
[root@Ansible-Master ~19:15]#ansible 192.168.213.123 -m setup -a "filter=ansible_os_family"
192.168.213.123 | SUCCESS => {
    "ansible_facts": {
        "ansible_os_family": "RedHat", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

本文标签: 模块 常用 基础 ansible doc