Ansible-基础及常用模块

安装

1. 准备yum源:

https://developer.aliyun.com/mirror/epel?spm=a2c6h.13651102.0.0.3fde1b11FsojqW

https://developer.aliyun.com/mirror/centos?spm=a2c6h.13651102.0.0.3e221b11CbELri

yum -y install ansible

2. 重要的配置文件

/etc/ansible/ansible.cfg  # 配置文件
/etc/ansible/hosts   # 主机清单
/etc/ansible/roles # 角色

修改ansible.cfg

复制代码
[root@master-1 clash]# egrep -v "^#|^$" /etc/ansible/ansible.cfg
[defaults]
inventory      = /etc/ansible/hosts
host_key_checking = False
log_path = /var/log/ansible.log
module_name = shell  # 修改默认模块为shell
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
复制代码

3. 配置ssh免密登录

4. 命令格式

host-pattern:主机分组

-m:模块名

-a:模块参数

-f:任务分批处理,进程数量,默认是5个

--limit  l  限制条件

限制只在某一台主机

ansible-playbook playbook.yml --limit webserver1.example.com

限制两主机组的并集(主机同时存在于这两主机组)

ansible-playbook playbook.yml --limit webserver1.example.com

限制在某个主机组执行,但不包含某台主机

ansible-playbook playbook.yml --limit  webservers:!webserver1.example.com

ansible 常用命令

5. 寻求模块方法帮助

ansible-doc -l  # 查看所有
ansible-doc  -s  ping   #  查看ping模块如何使用

6. 分组主机

复制代码
vim /etc/ansible/hosts

# 单台主机
# node1.m8s.com
node[1:2]

[nginx]
192.168.43.129
192.168.43.130
复制代码

7. 查看所有分组及主机

返回为图表

复制代码
ansible-inventory --graph
@all:
  |--@haproxy-keepalived:
  |  |--192.168.43.129
  |  |--192.168.43.132
  |  |--192.168.43.133
  |--@k8s-master:
  |  |--192.168.43.129
  |  |--192.168.43.132
  |  |--192.168.43.133
  |--@k8s-node:
  |  |--192.168.43.129
  |  |--192.168.43.130
  |  |--192.168.43.131
  |  |--192.168.43.132
  |  |--192.168.43.133
  |--@mysql:
  |  |--192.168.43.129
  |--@nginx:
  |  |--192.168.43.130
  |  |--192.168.43.131
  |--@redis:
  |  |--192.168.43.129
  |  |--192.168.43.130
  |  |--192.168.43.131
  |--@ungrouped:
复制代码

查看分组及服务,返回为json格式

复制代码
[root@kafka-1 rc.d]# ansible-inventory --list
{
    "_meta": {
        "hostvars": {}
    },
    "all": {
        "children": [
            "es",
            "mysql",
            "redis",
            "ungrouped",
            "web"
        ]
    },
    "es": {
        "hosts": [
            "192.168.64.16",
            "192.168.64.29"
        ]
    },
    "mysql": {
        "hosts": [
            "192.168.64.30"
        ]
    },
    "redis": {
        "hosts": [
            "192.168.64.32"
        ]
    },
    "web": {
        "hosts": [
            "192.168.64.12",
            "192.168.64.14"
        ]
    }
}
复制代码

jq 用法,取值

复制代码
[root@kafka-1 opt]# ansible-inventory --list | jq .es
{
  "hosts": [
    "192.168.64.16",
    "192.168.64.29"
  ]
}
[root@kafka
-1 opt]# ansible-inventory --list | jq .es[] [ "192.168.64.16", "192.168.64.29" ] 查看主机列表 [root@kafka-1 rc.d]# ansible all --list-hosts hosts (6): 192.168.64.12 192.168.64.14 192.168.64.32 192.168.64.30 192.168.64.16 192.168.64.29 [root@kafka-1 rc.d]# ansible web --list-hosts hosts (2): 192.168.64.12 192.168.64.14 ansible-inventory --list |jq .all
{ "children": [ "haproxy-keepalived", "k8s-master", "k8s-node", "mysql", "nginx", "redis", "ungrouped" ] }
复制代码

8. 多进程运行

默认情况下,Ansible 仅使用5个同时运行的进程。如果您拥有的主机数量多于为 fork 计数设置的值,则可能会增加 Ansible 与主机通信所需的时间。
要重新启动具有 10 个并行 fork 的 [atlanta] 服务器:

ansible atlanta -a "/sbin/reboot" -f 10

9. 自定义错误返回

# 部分主机返回 non-zero return code 错误,这表示在这些主机上执行的命令没有成功
# grep 80 不会找到任何匹配的行,因此 grep 返回的退出状态码会是 1

复制代码
[root@kafka-1 sbin]# ansible all -a 'netstat -ntpl |grep 80 ||The nginx 80 port is not listening'
192.168.64.12 | FAILED | rc=127 >>
/bin/sh: The: command not foundnon-zero return code
192.168.64.14 | CHANGED | rc=0 >>
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      17073/nginx: master
tcp6       0      0 :::9090                 :::*                    LISTEN      803/prometheus
192.168.64.16 | FAILED | rc=127 >>
/bin/sh: The: command not foundnon-zero return code
192.168.64.32 | FAILED | rc=127 >>
/bin/sh: The: command not foundnon-zero return code
192.168.64.30 | FAILED | rc=127 >>
/bin/sh: The: command not foundnon-zero return code
192.168.64.29 | FAILED | rc=127 >>
/bin/sh: The: command not foundnon-zero return code

[root@kafka-1 sbin]# ansible all -a 'netstat -ntpl |grep 80 ||echo "The nginx 80 port is not listening"'
192.168.64.12 | CHANGED | rc=0 >>
The nginx 80 port is not listening
192.168.64.14 | CHANGED | rc=0 >>
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      17073/nginx: master
tcp6       0      0 :::9090                 :::*                    LISTEN      803/prometheus
192.168.64.32 | CHANGED | rc=0 >>
The nginx 80 port is not listening
192.168.64.16 | CHANGED | rc=0 >>
The nginx 80 port is not listening
192.168.64.30 | CHANGED | rc=0 >>
The nginx 80 port is not listening
192.168.64.29 | CHANGED | rc=0 >>
The nginx 80 port is not listening
复制代码

10. 返回状态解释

绿色:成功,无更改。

黄色:成功,有更改。

红色:失败。

紫色:跳过。

蓝色:任务标题或进度。

灰色:调试信息。

白色:普通信息。

深红色:致命错误。

橙色:警告。

复制代码
]# ansible nginx -m ping
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
node2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
复制代码

常用模块

1. command模块,不支持特殊符号、正则

创建文件

]# ansible all -m command  -a 'mkdir /root/1.txt'
[WARNING]: Consider using the file module with state=directory rather than running 'mkdir'.  If you need to use command because file 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.
node1 | CHANGED | rc=0 >>

node2 | CHANGED | rc=0 >>

不支持正则符合

复制代码
[root@master-1 ~]# ansible nginx -m command  -a  "ls /usr/local/bin/*"
192.168.43.130 | FAILED | rc=2 >>
ls: 无法访问/usr/local/bin/*: 没有那个文件或目录non-zero return code
192.168.43.131 | FAILED | rc=2 >>
ls: 无法访问/usr/local/bin/*: 没有那个文件或目录non-zero return code

[root@master-1 ~]# ansible nginx -m shell  -a  "ls /usr/local/bin/*"
192.168.43.130 | CHANGED | rc=0 >>
/usr/local/bin/containerd
/usr/local/bin/containerd-shim
...
/usr/local/bin/kubelet
/usr/local/bin/kube-proxy

192.168.43.131 | CHANGED | rc=0 >>
/usr/local/bin/cfssl
/usr/local/bin/cfssl-certinfo
/usr/local/bin/cfssljson
/usr/local/bin/crictl
复制代码

2. shell模块,使用shell解释器执行

复制代码
]# ansible all -m shell -a "id user1 || useradd user1"
node2 | CHANGED | rc=0 >>
id: user1: no such user
node1 | CHANGED | rc=0 >>
id: user1: no such user

]# ansible all -m shell -a "id user1 || useradd user1"
node1 | CHANGED | rc=0 >>
uid=1002(user1) gid=1002(user1) groups=1002(user1)
node2 | CHANGED | rc=0 >>
uid=1001(user1) gid=1001(user1) groups=1001(user1)
复制代码

3. group模块

]# ansible node2 -m group -a "name=mygrp gid=2000 system=yes"     # 默认state为present
]# ansible node2 -m group -a "name=mygrp state=absent"  # 指定state为absent,表示remove mygrp

4. user模块

[root@master-1 ansible]# echo "123456" |openssl passwd -1  -stdin
$1$6NXikaln$64e67B6Q2C0xK0fuNkVw30

[root@master-1 ansible]# ansible nginx -m user -a 'name=es uid=1006 group=es shell=/bin/bash create_home=true password="$1$6NXikaln$64e67B6Q2C0xK0fuNkVw30"' # 注意此处加密密码需要用""

5. copy模块,拷贝数据到远端

注意:copy模块只适合拷贝单个文件copy 模块会逐个传输文件,每个文件都要建立 SSH 连接,导致大量小文件时效率低下。

默认 copy 不是增量复制,每次都会完整拷贝,即使目标已存在相同文件。

多个文件建议使用改synchronize(基于 rsync,速度快)

复制代码
examples:
- name: Copy a new "ntp.conf file into place, backing up the original if it differs from the copied version
  copy:
    src: /mine/ntp.conf
    dest: /etc/ntp.conf
    owner: root
    group: root
    mode: '0644'   # 八进制,标准写法
    backup: yes

# 目录不存在,自动创建
[root@master-1 ansible]# ansible nginx -m copy -a "src=./test.sh dest=/tmp/ansible/ "  

[root@master-1 ansible]# ansible nginx  -a "ls /tmp/ansible/ "
192.168.43.130 | CHANGED | rc=0 >>
test.sh
192.168.43.131 | CHANGED | rc=0 >>
test.sh

[root@master-1 ansible]# ansible nginx  -a "cat /tmp/ansible/test.sh "
192.168.43.130 | CHANGED | rc=0 >>
#!/bin/bash

echo "hello,ansible~"
192.168.43.131 | CHANGED | rc=0 >>
#!/bin/bash

echo "hello,ansible~"

拷贝文件并修改权限
ansible nginx -m copy -a "src=./test.sh dest=/tmp/ansible/test2.sh owner=nobody group=nobody mode=0644 backup=yes"

[root@master-1 ansible]# ansible nginx  -a "ls -l  /tmp/ansible/ "
192.168.43.130 | CHANGED | rc=0 >>
总用量 8
-rw-r--r-- 1 nobody nobody 35 2月   8 11:05 test2.sh
-rw-r--r-- 1 root   root   35 2月   8 11:03 test.sh
192.168.43.131 | CHANGED | rc=0 >>
总用量 8
-rw-r--r-- 1 nobody nobody 35 2月   8 11:05 test2.sh
-rw-r--r-- 1 root   root   35 2月   8 11:03 test.sh

[root@master-1 ansible]# ansible nginx  -a "bash /tmp/ansible/test2.sh "
192.168.43.131 | CHANGED | rc=0 >>
hello,ansible~
192.168.43.130 | CHANGED | rc=0 >>
hello,ansible~

# content写入文件
[root@master-1 playbook]# ansible nginx -m copy -a "content='echo hello world~' dest=/tmp/ansible/test5.sh"

[root@master-1 playbook]# ansible  nginx -a "ls -lrt /tmp/ansible/"
192.168.43.130 | CHANGED | rc=0 >>
总用量 20
-rw-r--r-- 1 nobody nobody 35 2月   8 11:05 test2.sh
-rwxr-x--- 1 nobody nobody 75 2月   9 13:06 test.sh
-rw-r--r-- 1 root   root   79 2月   9 15:49 test3.sh
-rw-r--r-- 1 root   root   15 2月   9 18:00 nohup.out
-rw-r--r-- 1 root   root   17 2月   9 18:36 test5.sh
192.168.43.131 | CHANGED | rc=0 >>
总用量 20
-rw-r--r-- 1 nobody nobody 35 2月   8 11:05 test2.sh
-rwxr-x--- 1 nobody nobody 75 2月   9 13:06 test.sh
-rw-r--r-- 1 root   root   79 2月   9 15:49 test3.sh
-rw-r--r-- 1 root   root   15 2月   9 18:00 nohup.out
-rw-r--r-- 1 root   root   17 2月   9 18:36 test5.sh
[root@master-1 playbook]# ansible  nginx -a "cat /tmp/ansible/test5.sh"
192.168.43.130 | CHANGED | rc=0 >>
echo hello world~
192.168.43.131 | CHANGED | rc=0 >>
echo hello world~
复制代码

6. fetch模块,只能是文件类型

拉取数据目录如果不指定,默认在当前目录

   1. 创建链接文件

   2. 修改属性

   3. 创建目录

复制代码
]# ansible node2 -m fetch -a "src=/tmp/fetch.txt dest=/tmp/fetch.txt"   # 从远端复制数据到本地
node2 | CHANGED => {
    "changed": true,
    "checksum": "a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0",
    "dest": "/tmp/fetch.txt/node2/tmp/fetch.txt",
    "md5sum": "ba1f2511fc30423bdbb183fe33f3dd0f",
    "remote_checksum": "a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0",
    "remote_md5sum": null
}
复制代码
]# cat  /tmp/fetch.txt/node2/tmp/fetch.txt
123

7. file模块,创建、修改文件/目录属性

(Choices: absent, directory, file, hard, link, touch)[Default: file]

复制代码
]# ansible node2 -m file -a "group=mygrp mode=0660 path=/tmp/fetch.txt"
node2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "gid": 2000,
    "group": "mygrp",
    "mode": "0660",
    "owner": "root",
    "path": "/tmp/fetch.txt",
    "size": 4,
    "state": "file",
    "uid": 0
}
复制代码
]# ll /tmp/fetch.txt
-rw-rw---- 1 root mygrp 4 May  4 18:19 /tmp/fetch.txt

 创建目录,如果目录不存在,会自动创建

复制代码
]# ansible node2 -m file -a "group=mygrp mode=0660 path=/tmp/filemode-test state=directory"   # state不指定,默认是文件类型
node2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "gid": 2000,
    "group": "mygrp",
    "mode": "0660",
    "owner": "root",
    "path": "/tmp/filemode-test",
    "size": 6,
    "state": "directory",
    "uid": 0
}
复制代码
]# ll
total 1796
-rw-rw----  1 root mygrp      4 May  4 18:19 fetch.txt
drw-rw----  2 root mygrp      6 May  4 18:55 filemode-test   # 目录类型

创建目录链接

复制代码
]# ansible node2 -m file -a "path=/tmp/filemode-test/fetch.txt  src=/tmp/fetch.txt state=link"
node2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "dest": "/tmp/filemode-test/fetch.txt",
    "gid": 0,
    "group": "root",
    "mode": "0777",
    "owner": "root",
    "size": 14,
    "src": "/tmp/fetch.txt",
    "state": "link",
    "uid": 0
}
复制代码

node2查看

]# ll filemode-test/
total 0
lrwxrwxrwx 1 root root 14 May  4 19:00 fetch.txt -> /tmp/fetch.txt
修改目录权限
- name: chown redis_dir
  ansible.builtin.file:
    path: /opt/redis_cluster
    owner: redis
    group: redis
    state: directory
    recurse: yes     # 递归修改

8. get_url 模块

 远程服务器下载文件,并且还可以指定文件权限,属主属组

ansible nginx -m get_url -a "url=https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/yum/7.0.0/apm-server-7.0.0-i686.rpm dest=/tmp mode=440"

[root@master-1 ansible]# ansible nginx -a "ls -l /tmp/apm*"
192.168.43.131 | CHANGED | rc=0 >>
-r--r----- 1 root root 12523551 2月   9 14:39 /tmp/apm-server-7.0.0-i686.rpm
192.168.43.130 | CHANGED | rc=0 >>
-r--r----- 1 root root 12523551 2月   9 14:39 /tmp/apm-server-7.0.0-i686.rpm

 9. cron 模块,如果要删除  state=absent 删除即可

复制代码
]# ansible all -m  cron -a "minute=*/5 job='/bin/bash /tmp/test.sh' name=test"   # job需要加''

# -name 注释信息
[root@master-1 ansible]# ansible nginx -m cron -a "minute=00 hour=* day=* month=* weekday=* job='/bin/bash /tmp/ansible/test.sh >/tmp/ansible/nohup.out' state=present name='hello world'"

[root@master-1 ansible]# ansible nginx -a "crontab -l"
192.168.43.131 | CHANGED | rc=0 >>
#Ansible: hello world
00 * * * * /bin/bash /tmp/ansible/test.sh >/tmp/ansible/nohup.out
192.168.43.130 | CHANGED | rc=0 >>
0 * * * * /opt/etcd/data/bak/etcd-bak.sh >/dev/null 2>&1
#Ansible: hello world
00 * * * * /bin/bash /tmp/ansible/test.sh >/tmp/ansible/nohup.out
复制代码

10. script模块

在远程服务器执行本地脚本

ansible nginx -m script -a 'test.sh'
ansible nginx -m script -a 'bash test.sh'  # 不能这样写
ansible nginx -m script -a 'test.sh start' # 可以传参

11. yum模块

present:如果软件包未安装,则安装它。如果软件包已安装,则不执行任何操作。
absent:移除
latest:更新

ansible nginx -m yum -a "name=redis state=present"

12. service与systemd模块

centos7/ubuntu16之后系统之前适用于service

复制代码
# 设置redis开机自启
ansible nginx -m service -a "name=redis enabled=yes"

[root@master-1 ~]# ansible nginx -a "systemctl is-enabled redis"
192.168.43.131 | CHANGED | rc=0 >>
enabled
192.168.43.130 | CHANGED | rc=0 >>
enabled

# 启动服务
ansible nginx -m service -a "name=redis state=started daemon_reload=yes"  # 执行systemctl daemon-reload
 
[root@master-1 ~]# ansible nginx -a "systemctl status  redis"
192.168.43.131 | CHANGED | rc=0 >>...
   Active: active (running) since 日 2025-02-09 11:23:23 CST; 19s ago
...192.168.43.130 | CHANGED | rc=0 >>..
   Active: active (running) since 日 2025-02-09 11:23:23 CST; 20s ago
...
复制代码

13. mount模块

安装nfs服务

apt-get install nfs-kernel-server
/srv/nfs 192.168.1.0/24(rw,sync,no_subtree_check)
/opt/nfs *(rw,sync,no_subtree_check)
sync:同步写入数据,保证数据的安全性。
no_subtree_check:不检查父目录的权限,提高效率。

挂载

[root@master-1 ansible]#  ansible nginx -m mount -a "src=192.168.43.132:/opt/nfs path=/data/es fstype=nfs opts=defaults,noatime state=mounted"

查看结果

复制代码
[root@master-1 ansible]# ansible nginx -a "cat /etc/fstab"
192.168.43.131 | CHANGED | rc=0 >>
UUID=c448318b-13ee-4077-8dd4-953120ea14c9 /                       xfs     defaults        0 0
UUID=632223b6-b444-4478-8261-ce08adcc0a0c /boot                   xfs     defaults        0 0
192.168.43.131:/data/loki /opt/loki   nfs defaults 0 0
UUID=eb600863-bef3-42a3-ac77-c28b5718d2b1 /kafka ext4 defaults 0 0
192.168.43.132:/opt/nfs /data/es nfs defaults,noatime 0 0
192.168.43.130 | CHANGED | rc=0 >> UUID=2782b022-83a4-438c-b94e-00c5c41e9b25 / xfs defaults 0 0 UUID=97672d99-8373-4242-b812-b0d1ae7e1703 /boot xfs defaults 0 0 192.168.43.131:/data/loki /opt/loki nfs defaults 0 0 192.168.43.132:/opt/nfs /data/es nfs defaults,noatime 0 0 [root@master-1 ansible]# ansible nginx -a "df -hT |grep 132" 192.168.43.130 | CHANGED | rc=0 >> 192.168.43.132:/opt/nfs nfs4 17G 11G 7.0G 60% /data/es 192.168.43.131 | CHANGED | rc=0 >> 192.168.43.132:/opt/nfs nfs4 17G 11G 7.0G 60% /data/es
复制代码

14. setup

获取主机相关信息

复制代码
[root@master-1 ansible]# ansible nginx -m setup -a "filter=ansible_default_ipv4"  # 过滤
192.168.43.131 | SUCCESS => {
    "ansible_facts": {
        "ansible_default_ipv4": {
            "address": "192.168.43.131",
            "alias": "ens33",
            "broadcast": "192.168.43.255",
            "gateway": "192.168.43.1",
            "interface": "ens33",
            "macaddress": "00:0c:29:6e:2a:60",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "192.168.43.0",
            "type": "ether"
        },
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}
192.168.43.130 | SUCCESS => {
    "ansible_facts": {
        "ansible_default_ipv4": {
            "address": "192.168.43.130",
            "alias": "ens33",
            "broadcast": "192.168.43.255",
            "gateway": "192.168.43.1",
            "interface": "ens33",
            "macaddress": "00:0c:29:38:22:1d",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "192.168.43.0",
            "type": "ether"
        },
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

 ansible nginx -m setup -a "filter=ansible_*_ipv4"  # 支持正则
复制代码

15. archive

在远程服务器进行打包

复制代码
exclude_path:排除,可能不好用,如果有这个需求,使用shell执行

- format
        The type of compression to use.
        Support for xz was added in Ansible 2.5.
        (Choices: bz2, gz, tar, xz, zip)[Default: gz]
        type: str
path:要进行压缩的文件或目录
dest:存储的路径
remove: 压缩完成后是否进行移除源文件,默认false

  archive:
    path:
    - /path/to/foo/
    - /path/wong/foo
    dest: /path/file.tar.bz2
    exclude_path:
    - /path/to/foo/bar
    - /path/to/foo/baz
    format: bz2

ansible nginx -m archive -a "path='/tmp/ansible/* /var/log/*' dest=/tmp/ansible-archive.tar.gz exclude_path=['/var/log/message', '/var/log/pods/'] format=gz"
复制代码

16. unarchive解压

remote_src: yes  使用目标主机的文件解压,不进行传输

复制代码
src: foo.tgz → **本地(控制节点)**的 foo.tgz 文件
dest: /var/lib/foo → 解压到远程主机的 /var/lib/foo
默认会将 foo.tgz 复制到远程机器 再解压
- name: Extract foo.tgz into /var/lib/foo
  unarchive:
    src: foo.tgz
    dest: /var/lib/foo

src: /tmp/foo.zip → 远程机器上的 /tmp/foo.zip
remote_src: yes → 不从控制节点传输文件,而是直接在远程机器解压
- name: Unarchive a file that is already on the remote machine
  unarchive:
    src: /tmp/foo.zip
    dest: /usr/local/bin
    remote_src: yes

从 URL 下载 并解压 → 方式 3
- name: Unarchive a file that needs to be downloaded (added in 2.0)
  unarchive:
    src: https://example.com/example.zip
    dest: /usr/local/bin
    remote_src: yes
复制代码

17. fetch 模块

将远程主机的文件拉取到ansible本地

 如果抓取多个主机的文件,ansible 会以主机ip或名称 创建对应目录存放拉取到的文件

- flat
允许您覆盖将主机名/路径/文件附加到目标的默认行为。
如果“dest”以“/”结尾,它将使用源文件的基本名称,类似于复制模块。
如果使用单个主机,或者检索每个主机唯一命名的文件,这将很有用。
如果使用具有相同文件名的多个主机,则每个主机的文件将被覆盖。
[默认值:False]
类型:bool
version_added:1.2
复制代码
[root@master-1 ansible]# ansible  nginx -m fetch -a "src=/tmp/ansible/test5.sh dest=/opt/ansible"
192.168.43.130 | CHANGED => {
    "changed": true,
    "checksum": "127716fac5fb00a750c931183a4ca99685105b7c",
    "dest": "/opt/ansible/192.168.43.130/tmp/ansible/test5.sh",
    "md5sum": "065bb662c5d713d38e5b0796edf4ebca",
    "remote_checksum": "127716fac5fb00a750c931183a4ca99685105b7c",
    "remote_md5sum": null
}
192.168.43.131 | CHANGED => {
    "changed": true,
    "checksum": "127716fac5fb00a750c931183a4ca99685105b7c",
    "dest": "/opt/ansible/192.168.43.131/tmp/ansible/test5.sh",
    "md5sum": "065bb662c5d713d38e5b0796edf4ebca",
    "remote_checksum": "127716fac5fb00a750c931183a4ca99685105b7c",
    "remote_md5sum": null
}
[root@master-1 ansible]# ll
总用量 4
drwxr-xr-x 3 root root  17 2月  11 10:00 192.168.43.130
drwxr-xr-x 3 root root  17 2月  11 10:00 192.168.43.131
drwxr-xr-x 3 root root  53 2月   9 21:03 playbook
-rwxr-xr-x 1 root root 199 2月  10 14:52 test.sh

[root@master-1 ansible]# ll 192.168.43.130
总用量 0
drwxr-xr-x 3 root root 21 2月  11 10:00 tmp
[root@master-1 ansible]# ll 192.168.43.130/tmp/ansible/test5.sh
-rw-r--r-- 1 root root 17 2月  11 10:00 192.168.43.130/tmp/ansible/test5.sh
[root@master-1 ansible]# ll 192.168.43.131/tmp/ansible/test5.sh
-rw-r--r-- 1 root root 17 2月  11 10:00 192.168.43.131/tmp/ansible/test5.sh
复制代码

18. Lineinfile 模块

用于 添加、修改或删除 特定的一行,主要适用于配置文件的管理。

主要特点
  • 匹配行:基于 regexp(正则表达式)或 line 直接匹配。
  • 修改或追加:如果匹配行存在,则修改;如果不存在,可以追加(insertbefore / insertafter)。
  • 确保幂等性:如果目标行已经符合要求,则不会重复修改。
示例
(1)修改或添加一行
- name: 确保配置文件中包含 `PermitRootLogin yes`
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin'
    line: 'PermitRootLogin yes'

解释

  • 如果 /etc/ssh/sshd_config已经有 PermitRootLogin xxx,它会修改该行。
  • 如果 没有 这行,它会自动添加 PermitRootLogin yes
(2)在某行之前或之后插入
- name: 在 `root ALL=(ALL) ALL` 之后插入 `admin ALL=(ALL) ALL`
  ansible.builtin.lineinfile:
    path: /etc/sudoers
    insertafter: '^root ALL=\(ALL\) ALL'
    line: 'admin ALL=(ALL) ALL'
(3)删除一行
- name: 删除 `PermitRootLogin no` 这一行
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin no'
    state: absent

19. Replace模块

用于 替换文件中所有匹配的内容,适用于大范围修改,不局限于单行。

主要特点
  • 基于正则匹配 进行替换。
  • 替换所有匹配项(不像 lineinfile 只作用于一行)。
  • 适用于批量修改文本
示例
(1)修改所有匹配的文本
- name: 将 `/var/www/html` 替换为 `/srv/web`
  ansible.builtin.replace:
    path: /etc/apache2/sites-available/000-default.conf
    regexp: '/var/www/html'
    replace: '/srv/web'

解释

  • 匹配 /var/www/html,并替换为 /srv/web
  • 所有匹配的地方都会被替换(不是仅限于某一行)。
(2)删除所有匹配的行
- name: 删除所有 `#DebugMode=on`(注释的调试模式)
  ansible.builtin.replace:
    path: /etc/app/config.ini
    regexp: '^#DebugMode=on'
    replace: ''

解释

  • 匹配 #DebugMode=on 并替换为空,即删除该行。
(3). lineinfile vs replace 适用场景
模块适用场景优点缺点
lineinfile 确保某个配置行存在或修改 幂等性强,适用于配置管理 不能批量替换
replace 批量替换文本(所有匹配项) 适用于大规模文本替换 非幂等,需要小心使用

4. 选择使用哪一个?
  • 如果你要修改或添加 特定的一行,使用 lineinfile。✅
  • 如果你要替换 所有匹配的内容,使用 replace。✅
  • 如果你要删除某行,两者都可以:
    • lineinfile 适合 删除特定的某行
    • replace 适合 删除所有匹配的内容

20. git 模块

 指定版本拉取

- git:
    repo: 'https://foosball.example.org/path/to/repo.git'
    dest: /srv/checkout
    version: release-0.22

对文档进行压缩

# Allowed archive formats ["zip", "tar.gz", "tar", "tgz"]
- git:
    repo: https://github.com/ansible/ansible-examples.git
    dest: /src/ansible-examples
    archive: /tmp/ansible-examples.zip

21. blockinfile模块

blockinfile 是 Ansible 用于管理 配置文件中的一段文本块 的模块,适用于 追加、更新或删除 目标文件中的多行配

参数说明默认值
path 目标文件路径 必填
block 需要插入的内容 必填
marker 标记文本块的起始和结束 # {mark} ANSIBLE MANAGED BLOCK
insertbefore 在匹配行前插入 EOF(默认末尾)
insertafter 在匹配行后插入 EOF(默认末尾)
create 文件不存在时是否创建 no
backup 修改前是否备份 no

1. 在 /etc/profile 添加 Java 环境变量

- name: 添加或更新文件中的文本块
  ansible.builtin.blockinfile:
    path: /etc/example.conf  # 目标文件路径
    block: |
      [example]
      key1 = value1
      key2 = value2
    marker: "# {mark} ANSIBLE MANAGED BLOCK"

再次运行 Playbook 时,不会重复添加,只会保持已有内容。 

参数解释:

marker: "# {mark} ANSIBLE MANAGED BLOCK"

生成注释

# BEGIN ANSIBLE MANAGED BLOCK - JAVA
export JAVA_HOME=/opt/jdk1.8.0_341
export CLASSPATH=.:/opt/jdk1.8.0_341/jre/lib/rt.jar:/opt/jdk1.8.0_341/lib/dt.jar:/opt/jdk1.8.0_341/lib/tools.jar
export PATH=/opt/jdk1.8.0_341/bin:$PATH
# END ANSIBLE MANAGED BLOCK - JAVA

2. 在指定行前插入内容

- name: 在匹配的行 **前** 插入文本块
  ansible.builtin.blockinfile:
    path: /etc/ssh/sshd_config
    insertbefore: "^#PermitRootLogin"
    block: |
      PermitRootLogin no

3. 在指定行后插入内容

- name: 在匹配的行 **后** 插入文本块
  ansible.builtin.blockinfile:
    path: /etc/sysctl.conf
    insertafter: "^net.ipv4.ip_forward"
    block: |
      net.ipv4.conf.all.rp_filter = 1

4. 确保文件存在(如果不存在则创建)

- name: 确保 `/etc/myconfig.conf` 存在并写入配置
  ansible.builtin.blockinfile:
    path: /etc/myconfig.conf
    create: yes
    block: |
      [myconfig]
      option1 = value1
      option2 = value2

如果 /etc/myconfig.conf 不存在,则 自动创建并写入 配置。

5. 修改前备份原文件

- name: 修改 `/etc/hosts` 并备份
  ansible.builtin.blockinfile:
    path: /etc/hosts
    backup: yes
    block: |
      192.168.1.100 myserver.local

6. 删除 blockinfile 插入的内容

- name: 从 `/etc/profile` 删除 Java 配置
  ansible.builtin.blockinfile:
    path: /etc/profile
    marker: "# {mark} ANSIBLE MANAGED BLOCK - JAVA"
    state: absent

只要 marker 里匹配 # {mark} ANSIBLE MANAGED BLOCK - JAVA 的内容,整块删除

blockinfile VS lineinfile
特性blockinfilelineinfile
作用 管理多行文本 仅管理单行
marker 标记插入内容 不适用
适用于 配置文件的整个区块 添加/修改单行

22. sysctl模块

复制代码
- sysctl:
    name: vm.swappiness
# 必须使用单引号'' value:
'5' state: present
# [Default: /etc/sysctl.conf] sysctl_file:
/tmp/test_sysctl.conf
# 相当于/sbin/sysctl -p reload: yes
复制代码

23. wait_for模块

wait_for 模块用于等待某个条件满足,比如等待端口开放、等待文件存在、等待指定的超时时间等。这个模块在部署过程中非常有用,尤其是在等待远程主机的某些服务就绪时。

state

state: started 仅指端口监听,不会对端口状态进行检测

检查端口时:

  “started”将确保端口处于打开状态

  “stopped”将检查端口是否已关闭
  “drained”将检查活动连接。
检查文件或搜索字符串时,“present”或“started”将确保文件或字符串在继续之前存在,“absent”将检查文件是否存在或被删除。

检查端口

复制代码
    - name: 等待 Elasticsearch 端口 9200 可用
      ansible.builtin.wait_for:
        #host: "{{ ansible_default_ipv4.address }}"
        host: "{{ ansible_host }}"
        port: "{{ listen_port }}"
        # 每 5 秒检查一次端口状态
        delay: 5
        # 总的等待超时时间(秒)。如果在这个时间内端口没有变得可用,任务将失败。
        timeout: 60
        state: started
      register: es_ready
      changed_when: false
复制代码

等待文件存在及指定内容

- name: 等待文件 /tmp/ready.txt 存在
  wait_for:
    path: /tmp/ready.txt
    search_regex: "^node.name"
    timeout: 60
    delay: 5

检查活动链接

- name: Wait for port 8000 of any IP to close active connections, ignoring connections for specified hosts
  wait_for:
    host: 0.0.0.0
    port: 8000
    state: drained
    exclude_hosts: 10.2.1.2,10.2.1.3

24. uri模块

uri 模块用于发送 HTTP 请求,并可以检查返回的状态码、响应内容等。它常用于验证 Web 服务是否正常运行、发送 API 请求等。

 对响应值进行包含测试

- name: Check that a page returns a status 200 and fail if the word AWESOME is not in the page contents
  uri:
    url: http://www.example.com
    return_content: yes
  register: this
  failed_when: "'AWESOME' not in this.content"

对访问端口的http状态检测

复制代码
- name: 等待 HTTP 服务返回 200
  uri:
    url: http://localhost:8080
    status_code: 200
  # 将uri模块执行的结果注册到变量result中
  register: result
  # 循环条件,表示任务会一直重复执行
  until: result.status == 200
  # 重试10次
  retries: 10
  # 间隔5s
  delay: 5
复制代码

发送post请求

复制代码
- name: 发送 JSON 数据
  uri:
    url: https://example.com/api
    method: POST
    body: '{"name": "Ansible", "type": "automation"}'
    body_format: json
    headers:
      Content-Type: "application/json"
    status_code: 201
    url_username: admin
    url_password: secret
    force_basic_auth: yes
    # 默认30s
    timeout: 30
    # 对于https请求,忽略证书校验
    validate_certs: no
复制代码

24. stat模块

stat 模块用于 检查远程主机上的文件或目录 是否存在,并获取 权限、大小、所有者等信息。
类似 Linux stat 命令,可用于 判断文件是否存在,从而决定是否执行后续任务。
注意: stat 模块无法直接读取文件内容,它只能获取文件的元数据(如是否存在、大小、权限、所有者等)

stat 常见参数

参数作用
path 必填,要检查的文件/目录路径
get_md5 是否获取文件 MD5 校验值(默认 false
get_checksum 是否获取 SHA1 校验值(默认 true
checksum_algorithm 指定校验算法,如 sha256
get_mime 获取文件 MIME 类型

 stat 返回信息

stat 返回一个字典,包含以下关键值:

返回字段说明
exists 是否存在 (true / false)
isdir 是否是目录
isreg 是否是普通文件
size 文件大小(字节)
mode 权限(八进制,如 0644
pw_name 所有者(用户名)
gr_name 所属组
checksum SHA1 校验值
md5 MD5 值(需要 get_md5: true
mime_type 文件 MIME 类型

1. 判断文件是否存在

复制代码
- name: 检查 nginx 配置文件
  ansible.builtin.stat:
    path: /etc/nginx/nginx.conf
  register: nginx_config

- name: 只有文件存在时才执行
  ansible.builtin.debug:
    msg: "nginx 配置文件存在"
  when: nginx_config.stat.exists   # 固定格式为xxx.stat.xxx
复制代码

2. 判断目录是否存在

复制代码
- name: 检查 /var/log 目录
  ansible.builtin.stat:
    path: /var/log
  register: log_dir

- name: 目录存在时执行
  debug:
    msg: "日志目录存在"
  when: log_dir.stat.isdir
复制代码

3. 判断文件大小

复制代码
- name: 检查文件大小
  ansible.builtin.stat:
    path: /var/log/messages
  register: log_file

- name: 如果日志文件超过 10MB,则删除
  ansible.builtin.file:
    path: /var/log/messages
    state: absent
  when: log_file.stat.exists and log_file.stat.size > 10485760
复制代码

📌 文件大于 10MB(10 * 1024 * 1024 字节)才删除

4. 获取文件权限

- name: 检查 /etc/passwd 权限
  ansible.builtin.stat:
    path: /etc/passwd
  register: passwd_file

- name: 输出文件权限
  debug:
    msg: "文件权限是 {{ passwd_file.stat.mode }}"

5. 判断二进制服务是否运行

- name: 检查 nginx.pid 是否存在
  ansible.builtin.stat:
    path: /var/run/nginx.pid
  register: nginx_pid

- name: 启动 nginx(如果未运行)
  ansible.builtin.shell: "/usr/sbin/nginx"
  when: not nginx_pid.stat.exists

📌 基于 pid 文件判断服务是否运行,不存在则启动。

6. 检测文件 MD5

复制代码
- name: 获取文件 MD5
  ansible.builtin.stat:
    path: /tmp/testfile
    get_md5: true
  register: file_stat

- name: 输出 MD5 值
  debug:
    msg: "文件 MD5 是 {{ file_stat.stat.md5 }}"
复制代码

扩展:

对文件内容进行判断

 方法 1:grep + shell(推荐)

复制代码
- name: 检查 nginx 配置文件中是否有 "server_name"
  ansible.builtin.shell: "grep 'server_name' /etc/nginx/nginx.conf"
  register: nginx_check
  ignore_errors: yes  # 如果 grep 失败(找不到字符串),不让 Playbook 终止

- name: 输出检查结果
  debug:
    msg: "找到 server_name 配置!"
  when: nginx_check.rc == 0
复制代码

方法 2:lineinfile 查找字符串

复制代码
- name: 检查 nginx.conf 是否包含 "server_name"
  ansible.builtin.lineinfile:
    path: /etc/nginx/nginx.conf
    line: "server_name example.com;"
    state: present
    check_mode: yes  # 仅检查,不修改
  register: check_nginx

- name: 输出文件是否包含该行
  debug:
    msg: "文件中已包含 server_name!"
  when: check_nginx.found > 0
复制代码

方法 3:读取整个文件内容并判断

原理

  • slurp 读取整个文件,并以 Base64 编码返回。
  • b64decode 进行解码,然后使用 Jinja2 过滤器查找字符串。
复制代码
- name: 读取 /etc/nginx/nginx.conf 内容
  ansible.builtin.slurp:
    path: /etc/nginx/nginx.conf
  register: file_content

- name: 判断文件内容是否包含 "server_name"
  debug:
    msg: "找到 server_name 配置"
  when: "'server_name' in file_content.content | b64decode"
复制代码

 25. synchronize模块

 

posted @   不会跳舞的胖子  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示