Ansible常用模块

ansible通过模块的方式来完成一些远程的管理工作

#查看所有模块
ansible-doc -l 
#查看某个模块的参数
ansible-doc -s module 
#查看某个模块更详细的信息
ansible-doc help module

setup:可以用来查看远程主机的一些基本信息

功能: setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度

可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息

# setup模块无任何参数
ansible all -m setup

ansible all -m setup -a "filter=ansible_nodename"

ansible all -m setup -a "filter=ansible_hostname"

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"

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"

ansible all -m setup -a "filter=ansible_processor_vcpus"

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_uptime_seconds"

ansible all -m setup -a "filter=ansible_processor*"

ansible all -m setup -a 'filter=ansible_env'

示例:获取 IPv4 地址

root@ubuntu20:~# ansible db -m setup -a "filter=ansible_all_ipv4_addresses"
10.0.0.16 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.18.1.4",
            "10.0.0.16",
            "172.17.0.1",
            "172.60.0.1"
        ],
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}
10.0.0.15 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.0.15",
            "172.18.1.125"
        ],
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}
root@ubuntu20:~#

示例

root@ubuntu20:~# ansible db -m setup -a 'filter=ansible_python_version'
10.0.0.15 | SUCCESS => {
    "ansible_facts": {
        "ansible_python_version": "3.8.6",
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}
10.0.0.16 | SUCCESS => {
    "ansible_facts": {
        "ansible_python_version": "3.8.6",
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}
root@ubuntu20:~#

ping:可以用来测试远程主机的运行状态

# ping模块无任何参数
ansible all -m ping

示例

root@ubuntu20:~# ansible db -m ping
10.0.0.16 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.15 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
root@ubuntu20:~#

authoried_keys

配置ansible到远程主机的ssh无密码登录的信任关系
参考:https://my.oschina.net/u/4306156/blog/3597849

首先采用Ansible批量建立ssh无密码登录的信任关系!!

[root@ansible-server ~]# ssh-keygen -t rsa          #一路回车
[root@ansible-server ~]# ls /root/.ssh/
id_rsa  id_rsa.pub
 
####################################################################################################
需要注意ssh建立互信的命令格式:
# ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip或hostname
####################################################################################################
 
在客户机比较多的情况下,使用 ssh-copy-id命令的方法显然是有些费时,使用ansible-playbook 推送 ymal进行批量创建ssh互信关系就显得省事多了,
这里就使用到了ansible的authoried_keys 模块:
 
首先要配置ansible清单 (远程主机的密码这里为"123456")
[root@ansible-server ~]# vim /etc/ansible/hosts
................
................
[ssh-host]
172.16.60.204
172.16.60.205
172.16.60.206
172.16.60.207
 
[ssh-host:vars]
ansible_ssh_pass="123456"
 
####################################################################################################
发送公钥到目标机器命令格式如下:
# ansible ssh-host -m copy -a "src=/root/.ssh/id_rsa.pub dest=/root/.ssh/authorized_keys mode=600"
####################################################################################################
在上面分发密钥中,如果清单文件/etc/ansible/hosts里没有使用ansible_ssh_pass变量指明密码,则可以使用下面命令:
这里默认ssh-host组下的机器root密码都一样,使用-k 参数,回车输入root密码即可:
# ansible ssh-host -m authorized_key -a "user=root state=present key=\"{{ lookup('file', '/root/.ssh/id_rsa.pub') }} \"" -k
####################################################################################################
 
# 编写playbook文件
[root@ansible-server ~]# vim /opt/ssh_key.yaml
---
  - hosts: ssh-host
    user: root
    tasks:
     - name: ssh-copy
       authorized_key: user=root key="{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"
 
# 注意上面yaml脚本中的"ssh-key-host"是在/etc/ansible/hosts清单文件里配置的远程客户机列表
这里做的是基于远程主机root用户的ssh互信
 
# 执行批量互信
[root@ansible-server ~]# ansible-playbook /opt/ssh_key.yaml
 

# 最后验证下ssh互信
[root@ansible-server ~]# ansible -i /etc/ansible/hosts ssh-host -m shell -a "whoami"

如果ansible服务端没有和远程主机做ssh信任关系, 则可以在hosts清单配置里直接指明用户名和密码.
如果使用普通用户, 并且允许sudo, 则需要提前在客户机里的/etc/sudoers文件里配置好该普通用户的sudo配置, 即允许该普通用户有sudo权限.
 
[root@ansible-server ~]# vim /etc/ansible/hosts
................
[test-host]
172.16.60.220 ansible_ssh_user=root ansible_ssh_pass=123456 ansible_ssh_port=22
172.16.60.221 ansible_ssh_user=root ansible_ssh_pass=bo@123 ansible_ssh_port=22
172.16.60.222 ansible_ssh_user=app ansible_ssh_pass=bj@123 ansible_ssh_port=22 ansible_sudo_pass=bj@123
 
即172.16.60.222客户机上要提前配置, 允许app用户具有sudo权限.

执行:
[root@ansible-server ~]# ansible test-host -m shell -a "hostname"                      
172.16.60.222 | SUCCESS | rc=0 >>
k8s-node02

172.16.60.220 | SUCCESS | rc=0 >>
k8s-master01

172.16.60.221 | SUCCESS | rc=0 >>
k8s-node01

[root@ansible-server ~]# ansible -i /etc/ansible/hosts test-host -m shell -a "hostname"
172.16.60.222 | SUCCESS | rc=0 >>
k8s-node02

172.16.60.220 | SUCCESS | rc=0 >>
k8s-master01

172.16.60.221 | SUCCESS | rc=0 >>
k8s-node01

Command 模块

功能:在远程主机执行命令,此为默认模块,可忽略 -m 选项

注意:

  • 此命令不支持 $VARNAME < > | ; & 等,可能用shell模块实现

  • 此模块不具有幂等性

语法

ansible [主机IP或组名] -m

command模块包含如下选项

header 1header 2
creates一个文件名,当该文件存在,则该命令不执行
free_from要执行的linux指令
chdir在执行指令之前,先切换到该指定的目录
removes一个文件名,当该文件不存在,则该选项不执行,和creates相反
executable切换shell来执行指令,该执行路径必须是一个绝对路径

示例

ansible db -m command -a 'chdir=/etc cat os-release'
# 简写
root@ubuntu20:~# ansible db -a 'chdir=/etc cat os-release'
10.0.0.16 | CHANGED | rc=0 >>
NAME="Ubuntu"
VERSION="20.10 (Groovy Gorilla)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.10"
VERSION_ID="20.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=groovy
UBUNTU_CODENAME=groovy
10.0.0.15 | CHANGED | rc=0 >>
NAME="Ubuntu"
VERSION="20.10 (Groovy Gorilla)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.10"
VERSION_ID="20.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=groovy
UBUNTU_CODENAME=groovy
root@ubuntu20:~#

# file2存在,所以ls /home不执行
ansible db -a 'creates=/tmp/file2 ls /home'

# /etc/fs不存在,所以cat /etc/fstab不执行
root@ubuntu20:~# ansible db -a 'removes=/etc/fs cat /etc/fstab'
10.0.0.16 | SUCCESS | rc=0 >>
skipped, since /etc/fs does not exist
10.0.0.15 | SUCCESS | rc=0 >>
skipped, since /etc/fs does not exist
root@ubuntu20:~#

# 进入/usr/local/src/目录,将jdk-6u45-linux-amd64.rpm打包
ansible mfs_node -a 'chdir=/usr/local/src/ tar zcf=bbb.tar.gz jdk-6u45-linux-amd64.rpm'

# 不成功,此命令不支持$VARNAME < > | ; & 等,要用shell模块实现
ansible db -m command -a 'echo adwl2020 |passwd --stdin adwl' ansible db -m command -a 'echo "adwl:adwl2021"|chpasswd'

Shell:和Command相似,用shell执行命令

功能:和command相似,用shell执行命令,支持各种符号,比如:*,$, >

注意:此模块不具有幂等性

语法

ansible [主机IP或组名] -m shell -a '要执行的命令'

示例

root@ubuntu20:~# ansible db -m command -a "chdir=/etc cat os-release|grep ID"
10.0.0.16 | FAILED | rc=1 >>
cat: 'os-release|grep': No such file or directory
cat: ID: No such file or directorynon-zero return code
10.0.0.15 | FAILED | rc=1 >>
cat: 'os-release|grep': No such file or directory
cat: ID: No such file or directorynon-zero return code
root@ubuntu20:~# ansible db -m shell -a "chdir=/etc cat os-release|grep ID"
10.0.0.16 | CHANGED | rc=0 >>
ID=ubuntu
ID_LIKE=debian
VERSION_ID="20.10"
10.0.0.15 | CHANGED | rc=0 >>
ID=ubuntu
ID_LIKE=debian
VERSION_ID="20.10"
root@ubuntu20:~#

示例

ansible srv -m shell -a 'echo adwl2020 |passwd --stdin adwl'
ansible 192.168.30.* -m shell -a 'echo $HOSTNAME'
ansible 192.168.30.* -m shell -a 'cat /dev/null > /tmp/testfie'

# 调用bash执行命令,类似cat /tmp/stanley.md | awk -F '|' '{print $1,$2}' &> /tmp/example.txt这些复杂的命令,即使用shell也可以会失败,
# 解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器

最近在使用ansible shell模块启动一个shell编写的脚本,该脚本主要功能式加载java的classpath并在后台运行这个java程序。
该脚本在linux shell中可以正常启动和停止,但是使用ansible shell模块却每次都启动后进程都消失了,日志没有任何异常,pid文件也生成了。
后来经过一个同事的猜想,是否有程序将该进程kill掉了。

于是产生了以下几种猜想:
1.ansible shell模块执行完shell脚本,就立即关闭当前的shell,进程也就被关闭了。
2.ansible fork出来子线程来运行脚本,ansible正常退出时会结束所有fork的子线程因为程序启动后被关闭.

尝试解决: 给shell命令开头加个nohup, 结尾加个&, 如果环境变量找不到,加入source ~/.bash_profile
例如:source ~/.bash_profile;nohup /apps/xxx/ss/start.sh &

注意:调用bash执行命令 类似 cat /tmp/test.md | awk -F'|' '{print $1,$2}' &> /tmp/example.txt 这些复杂命令,即使使用shell也可能会失败,解决办法:写到脚本时,copy到远程,执行,再把需要的结果 拉回执行命令的机器

[root@ansible ~]#vim /etc/ansible/ansible.cfg 
# 修改下面一行
module_name = shell

范例:将shell模块代替command,设为模块

疑问:既然 shell 模板这么强大,可以直接取代 command、file、yum等模块,那为什么还需要使用其他模块呢?

答案:shell 模块虽然可以代替yum模块执行软件包管理、代替file 模块执行文件管理的功能,但并不具备幂等性和安全性

Script:运行脚本

功能:在远程主机上运行ansible服务器上的脚本(不需要将脚本复制到被控端,无需执行权限)

注意:此模块不具有幂等性

语法

ansible [主机IP或组名] -m script -a [脚本文件]

示例

# 在ansible管理机上编写脚本即可
cat f1.sh
#!/bin/bash
hostname
chmod +x f1.sh
# 在所有被监控机执行shell脚本,不用将脚本放在被监控机上
ansible all -m script -a '/search/odin/f1.sh'

#线上示例
[@bjyf_50_20 ansible]$ cat extserver_hosts
[all]
10.162.33.57
10.162.33.59
10.162.33.65
10.162.33.66
10.162.33.80
10.162.33.85
10.162.33.61
[all:vars]
ansible_ssh_pass="noSafeNoWork@2020"
anisble_ssh_user="root"
[@bjyf_50_20 ansible]$ cat f1.sh
#!/bin/bash
hostname

# 测试执行
[@bjyf_50_20 ansible]$ ansible -i extserver_hosts all -u root -m script -a 'f1.sh'

# 安装supervisor
[@bjyf_50_20 ansible]$ ansible -i extserver_hosts all -u root -m script -a 'install_supervisor.sh'

copy模块-------复制ansible主机的文件到远程主机

功能:从ansible服务器主控端复制文件到远程主机

注意: src=file 如果是没指明路径,则为当前目录或当前目录下的files目录下的file文件

官网:https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html

copy模块包含如下选项

header 1header 2
backup在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes
content用于替代"src",可以直接设定指定文件的值
dest必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
directory_mode递归的设定目录的权限,默认为系统默认权限
force如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,
则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
others所有的file模块里的选项都可以在这里使用
remote_src如果在远程机器上执行copy,相当于在远端机器本机执行cp命令,remote_src: true。
对于asible 2.6,只支持copy单个文件,不允许递归copy。
对于ansible 2.8 已经支持递归复制。
src要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。
在这种情况下,如果路径使用"/“来结尾,则只复制目录里的内容,如果没有使用”/"来结尾,则包含目录在内的
整个内容全部复制,类似于rsync。

示例

# /search/odin/bin bin目录自身和目录里面的文件都备份到dest指定的文件夹
copy: src=/search/odin/bin dest=/search/odin/backup/{{ bak_var.stdout }}/  remote_src=yes

# /search/odin/bin/ 只备份bin目录里面的文件到dest指定的文件夹
copy: src=/search/odin/bin/ dest=/search/odin/backup/{{ bak_var.stdout }}/  remote_src=yes

示例

# 关闭所有机器的Selinux
# 可以修改管理机的/etc/sysconfig/selinux文件
cat /etc/sysconfig/selinux
SELINUX=disabled


# 将文件拷贝到被管理机器,如目标存在,默认覆盖,此处指定先备份
ansible db -m copy -a 'src=/etc/sysconfig/selinux dest=/etc/sysconfig/selinux backup=yes'

# 复制文件bbb到远程目录:
ansible db -m copy -a 'src=bbb dest=/tmp/file2 mode=755 owner=root group=root'
ansible db -a 'cat /tmp/file2'

# 如果目标存在,默认覆盖,此处指定先备份
ansible db -m copy -a 'src=bbb dest=/tmp/file2 mode=755 owner=root group=root backup=yes'
ansible db -a 'cat /tmp/file2'

# 利用指定内容,直接生成目标文件
ansible db -m copy -a "content='test content\n' dest=/tmp/f1.txt"

Get_url 模块

功能: 用于将文件从http、https或ftp下载到被管理机节点上

常用参数

header 1header 2
url下载文件的URL,支持HTTP,HTTPS或FTP协议
dest下载到目标路径(绝对路径),如果目标是一个目录,就用服务器上面文件的名称,
如果目标设置了名称就用目标设置的名称
owner指定属主
group指定属组
mode指定权限
force如果yes,dest不是目录,将每次下载文件,如果内容改变,替换文件。
如果否,则只有在目标不存在时才会下载该文件
checksum对目标文件在下载后计算摘要,以确保其完整性
示例:
checksum="sha256:D98291AC[...]B6DC7B97",
checksum="sha256:http://example.com/path/sha256sum.txt"
url_username用于HTTP基本认证的用户名。对于允许空密码的站点,此参数可以不使用url_password
url_password用于HTTP基本认证的密码。如果未指定url_username参数,则不会使用url_password参数
validate_certs如果“no”,SSL证书将不会被验证。适用于自签名证书在私有网站上使用
timeoutURL请求的超时时间,秒为单位

示例

root@ubuntu20:~# ansible db -m get_url -a'url=http://nginx.org/download/nginx-1.18.0.tar.gz dest=/usr/local/src/nginx.tar.gz checksum="md5:b2d33d24d89b8b1f87ff5d251aa27eb8"'
10.0.0.16 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum_dest": null,
    "checksum_src": "47b2c5ccd12e2a7088b03d629ff6b9ab18215180",
    "dest": "/usr/local/src/nginx.tar.gz",
    "elapsed": 6,
    "gid": 0,
    "group": "root",
    "md5sum": "b2d33d24d89b8b1f87ff5d251aa27eb8",
    "mode": "0644",
    "msg": "OK (1039530 bytes)",
    "owner": "root",
    "size": 1039530,
    "src": "/root/.ansible/tmp/ansible-tmp-1621674758.5972314-6460-48209020573716/tmp89g8bing",
    "state": "file",
    "status_code": 200,
    "uid": 0,
    "url": "http://nginx.org/download/nginx-1.18.0.tar.gz"
}
10.0.0.15 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "checksum_dest": null,
    "checksum_src": "47b2c5ccd12e2a7088b03d629ff6b9ab18215180",
    "dest": "/usr/local/src/nginx.tar.gz",
    "elapsed": 19,
    "gid": 0,
    "group": "root",
    "md5sum": "b2d33d24d89b8b1f87ff5d251aa27eb8",
    "mode": "0644",
    "msg": "OK (1039530 bytes)",
    "owner": "root",
    "size": 1039530,
    "src": "/root/.ansible/tmp/ansible-tmp-1621674759.1839962-6459-130540770817695/tmpdp0h0nc7",
    "state": "file",
    "status_code": 200,
    "uid": 0,
    "url": "http://nginx.org/download/nginx-1.18.0.tar.gz"
}
root@ubuntu20:~#

Fetch:从客户端取文件至服务器端,copy相反,目录可先tar

功能:从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录

ansible-doc -s fetch
# 抓取所有被监控机的日志(只能抓取单个文件)
mkdir /log
ansible all -m ftech -a 'src=/var/log/message dest=/log/'

#抓取所有日志文件
ansible all -m shell -a 'tar jcf log.tar.xz /var/log/*.log'
ansible all -m ftech -a 'src=/root/log.tar.xz dest=/log/'
tar tvf log.tar.xz

示例

root@ubuntu20:~# ansible 10.0.0.11 -m fetch -a 'src=/root/script/for_user.sh dest=/tmp'
10.0.0.11 | SUCCESS => {
    "changed": false,
    "checksum": "a3d4cefd470383ea4c80f12464a0cf953b26597c",
    "dest": "/tmp/10.0.0.11/root/script/for_user.sh",
    "file": "/root/script/for_user.sh",
    "md5sum": "3cb5c8efcecbee10583b33c40a611f15"
}
root@ubuntu20:~# ll /tmp/10.0.0.11/root/script/for_user.sh
-rw-r--r-- 1 root root 353  5月 22 17:18 /tmp/10.0.0.11/root/script/for_user.sh
root@ubuntu20:~

示例

root@ubuntu20:~# ansible web -m  fetch -a 'src=/etc/os-release dest=/data/os'
10.0.0.15 | SUCCESS => {
    "changed": false,
    "checksum": "ccb4459029c37b82e2e29bd2bc138ec241490521",
    "dest": "/data/os/10.0.0.15/etc/os-release",
    "file": "/etc/os-release",
    "md5sum": "22ab75a1abcb3fc44748307848e32ae6"
}
10.0.0.11 | SUCCESS => {
    "changed": false,
    "checksum": "6e35f19e5774acd00f10342edef82a8247674028",
    "dest": "/data/os/10.0.0.11/etc/os-release",
    "file": "/etc/os-release",
    "md5sum": "0868a2ea7fc0d17dec85d63f452563d4"
}
root@ubuntu20:~# tree /data/os
/data/os
├── 10.0.0.11
│   └── etc
│       └── os-release
└── 10.0.0.15
    └── etc
        └── os-release

4 directories, 2 files
root@ubuntu20:~#

File:设置文件属性

功能:设置文件属性,创建软链接等

# 查看帮助
ansible-doc -s file
选项说明
force需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;
另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes
group定义文件/目录的属组
mode定义文件/目录的权限
owner定义文件/目录的属主
path必选项,定义文件/目录的路径
recurse递归的设置文件的属性,只对目录有效
src要被链接的源文件的路径,只应用于state=link的情况
dest被链接到的路径,只应用于state=link的情况
statedirectory:如果目录不存在,创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件

示例

# 创建软连接,将/etc/fstab软连到/tmp/fstab
ansible web -m file -a "src=/etc/fstab dest=/tmp/fstab state=link"
# 在master上或者test上查看结果:
ansible web -a "ls -lh /tmp"
#删除软连接
ansible web -m file -a "dest=/tmp/fstab state=absent"


# 在master上删除;-m  指定模块 ;-a  指定模块参数
ansible web -m file -a 'path=/tmp/fstab state=absent'
ansible web -m file -a 'path=/etc/yum.repos.d/xxx.repo state=absent' 

# 在 web创建file1文件
ansible web -m file -a 'path=/tmp/file1 state=touch'
ansible web -m file -a 'path=/tmp/file2 owner=song mode=755'
# 删除file1文件
ansible web -m file -a 'path=/tmp/file1 state=absent' 
# 查看文件
ansible web -m shell -a 'ls /tmp -lh'

# 在we上创建文件夹
ansible we -m file -a 'path=/tmp/d1 state=directory owner=root group=root mode=755'
# 删除文件夹
ansible web -m file -a 'path=/tmp/d1 state=absent'


# 递归修改目录属性,但不递归至子目录
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"

# 递归修改目录及子目录的属性
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql recurse=yes"

service模块

功能:管理服务

选项说明
arguments给命令行提供一些选项
enabled是否开机启动 yes
name必选项,服务名称
pattern定义一个模式,如果通过status指令来查看服务的状态时,
没有响应,就会通过ps指令在进程中根据该模式进行查找,
如果匹配到,则认为该服务依然在运行
runlevel运行级别
sleep如果执行了restarted,在则stop和start之间沉睡几秒钟
state对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)

示例

# 启动服务(并设置开启自启动)
ansible web -m service -a 'name=nginx state=started enabled=yes'
ansible web -m raw -a 'ps -ef|grep nginx'
ansible web -m service -a 'name=nginx state=stopped enabled=yes'

# 重新加载
ansible web -m service -a 'name=nginx state=reloaded'
ansible web -m raw -a 'ps -ef|grep nginx'
ansible web -m service -a 'name=nginx state=restarted sleep=3'
ansible web -m service -a 'name=network state=restarted args=eth0'
ansible web -m service -a 'name=foo pattern=/usr/bin/foo state=started'

user模板

功能:管理用户

选项解释
home指定用户的家目录,需要与createhome配合使用
groups指定用户的属组
uid指定用的uid
password指定用户的密码,注意:passwd的值不能是明文,
passwd关键字后面应该是密文,且密文将被保存在/etc/shadow文件中
name指定用户名
createhome是否创建家目录 yes
system是否为系统用户
remove当state=absent时,remove=yes则表示连同家目录一起删除,等价于userdel -r
state是创建还是删除(present,absent)
shell指定用户的shell环境
generate_ssh_key是否为相关用户生成SSH密钥。 这不会覆盖现有的SSH密钥。
ssh_key_bits可选择指定要创建的SSH密钥中的位数。
ssh_key_passphrase设置SSH密钥的密码, 如果没有提供密码,SSH密钥将默认没有密码。
ssh_key_file指定SSH密钥文件名(可选)
如果这是一个相对的文件名,那么它将是相对于用户的主目录。
ssh_key_type指定要生成的SSH密钥的类型(可选)
可用的SSH密钥类型将取决于目标主机上的实现。

示例

# 使用user模块创建用户
ansible w1 -m user -a 'name=nginx shell=/sbin/nologin system=yes home=/var/nginx group=nginx groups=root,bin uid=80 comment="nginx service" create_home=no non_unique=yes'
ansible w1 -a 'getent passwd nginx'

ansible web -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root'

ansible web -m user -a 'name=sysuser1 system=yes home=/app/sysuser1'

# 生成song123加密的密码
root@ubuntu20:~# ansible localhost -m debug -a "msg={{ 'song123'| password_hash('sha512','salt')}}"
localhost | SUCCESS => {
    "msg": "$6$salt$YjkHZzCRK8Kl2B6mGzlYbO7MlpZIa0AbpM36P/NaQPOgmLCK2H0obwdY6V47h/UFsB/cL.VYdt6P6Uk0FWBar0"
}
root@ubuntu20:~#

# 用上面创建的密码创建用户
ansible web -m user -a 'createhome=yes home=/home/user1 password="$6$salt$YjkHZzCRK8Kl2B6mGzlYbO7MlpZIa0AbpM36P/NaQPOgmLCK2H0obwdY6V47h/UFsB/cL.VYdt6P6Uk0FWBar0" name=user1 state=present shell=/bin/bash'

# 创建用户adwl,并生成4096bit的私钥
ansible web -m user -a 'name=adwl generate_ssh_key=yes ssh_key_bits=4096 ssh_key_file=.ssh/id_rsa'
 
# 使用user模块删除用户(删除家目录remove=yes,默认remove=no)
ansible web -m user -a 'remove=yes state=absent name=user1'

Ansible批量更新远程主机用户密码方法

方法一: 使用Ansible的user模块批量修改远程客户机的用户密码

#由于在使用ansible修改用户密码的时候不能使用明文的方式,需要先加密,所以就需要使用一个方法对输入的明文的密码进行加密.
cat /opt/root_passwd.yaml
---
  - hosts: ssh-host
    gather_facts: false
    tasks:
    - name: change user passwd
      user: name={{ item.name }} password={{ item.chpass | password_hash('sha512') }}  update_password=always
      with_items:
        - { name: 'root', chpass: 'kevin@123' }
        - { name: 'app', chpass: 'bjop123' }

#注意上面在yaml文件中修改了远程客户机的root用户密码, app用户密码. 
#如果还想要修改其他用户密码, 则继续按照上面规则添加即可!

#执行ansible-play
ansible-playbook /opt/root_passwd.yaml 

方法二: 修改远程主机的单个用户密码使用此方法比较方便

# 编写playbook文件
cat /opt/root_passwd2.yaml
---
  - hosts: ssh-host
    gather_facts: false
    tasks:
    - name: Change password
      user: name={{ name1 }}  password={{ chpass | password_hash('sha512') }}  update_password=always

# 执行ansible-playbook,  使用-e参数传递用户名和密码给剧本,其中root为用户名,admin#123就是修改后的root密码
ansible-playbook /opt/root_passwd2.yaml -e "name1=root chpass=admin#123"            

方法三: 使用如下Ansible脚本, 适用于修改清单中部分远程主机的用户密码

#编写ansible-playbook脚本 (需要注意下面脚本中"ens192"是客户机ip所在的网卡设备名称, 这个要根据自己实际环境去配置, 比如eth0, eth1等)
cat /opt/root_passwd4.yaml 
- hosts: test-host
  remote_user: root
  tasks:
  - name: change password for root
    shell: echo '{{ item.password }}' |passwd --stdin root
    when: ansible_ens192.ipv4.address  == '{{ item.ip }}'
    with_items:
      - { ip: "172.16.60.220", password: 'haha@123' }
      - { ip: "172.16.60.221", password: 'kevin@123' }
      - { ip: "172.16.60.222", password: 'bobo@123' }

# 执行ansible-playbook:
ansible-playbook /opt/root_passwd3.yaml

group:管理组

# 查看帮助
ansible-doc -s group
# 创建组
ansible web -m group -a "name=nginx system=yes gid=80"
# 验证
ansible web -a 'getent group nginx'
# 删除组
ansible web -m group -a "name=nginx state=absent"

Hostname 模块

功能:管理主机名

示例

ansible node1 -m hostname -a "name=web001"
ansible 10.162.0.11 -m hostname -a 'name=node002.update.south'

yum 和 apt 模块

功能:yum 管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本

apt 模块管理 Debian 相关版本的软件包

yum 包含如下选项

header 1header 2
config_fileyum的配置文件
disable_gpg_check关闭gpg_check
disablerepo不启用某个源
enablerepo启用某个源
name要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径
state状态(present,absent,latest)

示例:

# 安装
ansible web -m yum -a 'name=httpd state=latest'
ansible web -m yum -a 'name=httpd state=present'
# 启用 epel 源进行安装
ansible websrvs -m yum -a 'name=nginx state=present enablerepo=epel' 

# 升级除 kernel 和 foo 开头以外的所有包
ansible websrvs -m yum -a 'name=* state=lastest exclude=kernel*,foo*' 

# 删除
ansible web -m yum -a 'name=httpd state=absent'

# 安装多个包
ansible web -m yum -a 'name=httpd,nginx,redis state=latest'

# 卸载多个包
ansible web -m yum -a 'name=httpd,nginx,redis state=absent'

# 查看yum.repos.d文件夹
ansible web -m command -a 'ls /etc/yum.repos.d/'

# 删除xxx.repo文件
ansible web -m file -a 'path=/etc/yum.repos.d/xxx.repo state=absent' 

# 更改yum源
ansible all -m copy -a 'src=/etc/yum.repos.d/163.repo dest=/etc/yum.repos.d/163.repo'
ansible web -m yum -a 'name=httpd state=installed'
ansible web -m service -a 'name=httpd state=started'
ansible web -m shell -a 'ps -ef|grep httpd'

# 清除更新缓存
ansible 10.162.35.10[1-2] -m yum -a 'name=httpd update_cache=yes'

示例

[root@ansible ~]#ansible websrvs -m yum -a
"name=https://mirror.tuna.tsinghua.edu.cn/zabbix/zabbix/5.2/rhel/7/x86_64/zabbix-agent-5.2.5-1.el7.x86_64.rpm"

示例:查看包

ansible localhost -m yum -a "list=tree"

yum_repository 模块

- name: Add multiple repositories into the same file (1/2)
  yum_repository:
    name: epel
    description: EPEL YUM repo
    file: external_repos
    baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
    gpgcheck: no

- name: Add multiple repositories into the same file (2/2)
  yum_repository:
    name: rpmforge
    description: RPMforge YUM repo
    file: external_repos
    baseurl: http://apt.sw.be/redhat/el7/en/$basearch/rpmforge
    mirrorlist: http://mirrorlist.repoforge.org/el7/mirrors-rpmforge
    enabled: no

- name: Remove repository from a specific repo file
  yum_repository:
    name: epel
    file: external_repos
    state: absent    

示例:创建和删除仓库

cat yum_repo.yml
---
- hosts: websrvs
  remote_user: root
  gather_facts: no
  
  tasks:
    - name: Add multiple repositories into the same file
      yum_repository:
        name: test
        description: EPEL YUM repo
        file: external_repos
        baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
        gpgcheck: no
ansible-playbook  yum_repo.yml
cat /etc/yum.repos.d/external_repos.repo

cat remove_yum_repo.yml
---
- hosts: websrvs
  remote_user: root
  gather_facts: no
  
  tasks:
    - name: remove repo
      yum_repository:
        name: test
        file: external_repos
        state: absent

ansible-playbook  remove_yum_repo.yml

cron模块:用于管理计划任务

功能:计划任务

支持时间:minute,hour,day,month,weekday

包含如下选项

header 1header 2
backup对远程主机上的原任务计划内容修改之前做备份
cron_file如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划
day日(1-31,/2,……)
hour小时(0-23,/2,……)
minute分钟(0-59,/2,……)
month月(1-12,/2,……)
weekday周(0-7,*,……)
job要执行的任务,依赖于state=present
name该任务的描述
special_time指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly
state确认该任务计划是创建还是删除
user以哪个用户的身份执行

示例

#创建计划任务:每周二的5点重启机器
ansible t1 -m cron -a 'name="rebootSystem" minute=0 hour="5" day=0 month=0 weekday=2 user=root job="/sbin/reboot"'

# 查看计划任务
ansible t1 -m shell -a 'crontab -l'

# 禁用计划任务(必须加 name 选项)
ansible all -m cron -a 'disabled=true name="rebootSystem" job="/sbin/reboot"'

#启用计划任务
ansible all -m cron -a 'disabled=false name="rebootSystem" job="/sbin/reboot"'

# 删除计划任务,直接写上name删除
ansible t1 -m cron -a 'name="rebootSystem" minute=0 hour="5" day=0 month=0 weekday=2 user=root job="/sbin/reboot" state=absent'
ansible test -m cron -a 'name="rebootSystem"  state=absent'

# 创建计划任务,每3分钟显示一次home目录
ansible test -m cron -a 'name="check home directory" minute=*/3 job="ls -lh /home"'
# 查看计划任务
ansible test -m command -a 'crontab -l'

#创建计划任务,指定时间执行
ansible test -m cron -a 'name="check home directory" special_time=reboot job="echo reboot"'

示例

# 备份数据库脚本
[root@centos8 ~]#cat /root/mysql_backup.sh
#!/bin/bash
mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql_`date +%F_%T`.sql.gz

# 创建任务
ansible 10.0.0.11 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'

ansible db -m cron -a "minute=*/5 job='/usr/sbin/ntpdate ntp.aliyun.com &>/dev/null' name=Synctime"

# 禁用计划任务
ansible db -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=yes"

# 启用计划任务
ansible db -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=no"

# 删除任务
ansible db -m cron -a "name='backup mysql' state=absent"
ansible db -m cron -a 'state=absent name=Synctime'

synchronize-----使用rsync同步文件

Ansible synchronize模块主要用于目录、文件的同步,主要基于rsync命令工具同步目录和文件

Ansible synchronize模块详解

header 1header 2
compress开启压缩,默认为开启
archive是否采用归档模式同步,保证源文件和目标文件属性一致
checksum是否效验
dirs以非递归的方式传送目录
links同步链接文件
recursive是否递归yes/no
rsync_opts使用rsync的参数
copy_links同步的时候是否复制链接
delete删除源中没有但目标存在的文件,使两边内容一样,以推送方为主
src源目录及文件
dest目标文件及目录
dest_port目标接收的端口
rsync_path服务的路径,指定rsync在远程服务器上执行
rsync_remote_user设置远程用户名
–exclude=.log忽略同步以.log结尾的文件,这个可以自定义忽略什么格式的文件,
或者.txt等等都可以,但是由于这个是rsync命令的参数,
所以必须和rsync_opts一起使用,比如rsync_opts=–exclude=.txt这种模式
mode同步的模式,rsync同步的方式push、pull,默认是推送push,
从本机推送给远程主机,pull表示从远程主机上拿文件

示例:

ansible-doc -s synchronize

# 查看目录是否存在
ansible test -m file -a 'path=/var/www/ state=directory'

# 使用synchronize模块同步文件
ansible test -m synchronize -a 'src=/tmp/helloworld dest=/var/www/'
ansible test -a 'cat /var/www/helloworld'

# 使用synchronize模块同步目录
ansible test -m synchronize -a 'src=/etc/ansible/playbooks dest=/tmp/ mode=push'

filesystem模块—在块设备上创建文件系统

#包含如下选项: 
dev:目标块设备
force:在一个已有文件系统的设备上强制创建
fstype:文件系统的类型
opts:传递给mkfs命令的选项

mount-----配置挂载点

dump:
fstype:必选项,挂的文件的类型
name:必选项,挂载点

stat 模块

功能:检查文件或文件系统的状态

注意:对于Windows目标,请改用win_stat模块

选项

path:文件/对象的完整路径(必须)

常用的返回值判断

exists: 判断是否存在

isuid: 调用用户的ID与所有者ID是否匹配

示例

root@ubuntu20:~# ansible 127.0.0.1 -m stat -a 'path=/root/testfile'
127.0.0.1 | SUCCESS => {
    "changed": false,
    "stat": {
        "atime": 1620783434.6542244,
        "attr_flags": "e",
        "attributes": [
            "extents"
        ],
        "block_size": 4096,
        "blocks": 8,
        "charset": "us-ascii",
        "checksum": "9296e63da2444e14deac52fb58499ee02373ef5b",
        "ctime": 1620783429.9102886,
        "dev": 2049,
        "device_type": 0,
        "executable": false,
        "exists": true,
        "gid": 0,
        "gr_name": "root",
        "inode": 5509736,
        "isblk": false,
        "ischr": false,
        "isdir": false,
        "isfifo": false,
        "isgid": false,
        "islnk": false,
        "isreg": true,
        "issock": false,
        "isuid": false,
        "mimetype": "text/plain",
        "mode": "0644",
        "mtime": 1620783429.9102886,
        "nlink": 1,
        "path": "/root/testfile",
        "pw_name": "root",
        "readable": true,
        "rgrp": true,
        "roth": true,
        "rusr": true,
        "size": 45,
        "uid": 0,
        "version": "4282118675",
        "wgrp": false,
        "woth": false,
        "writeable": true,
        "wusr": true,
        "xgrp": false,
        "xoth": false,
        "xusr": false
    }
}
root@ubuntu20:~#

示例

- name: install  | Check if  file is already configured.
  stat: path={{ nginx_file_path }}
  connection: local
  register: nginx_file_result
- name: install | Download nginx file
  get_url: url={{ nginx_file_url }} dest={{ software_files_path }}
validate_certs=no
  connection: local
  when:,not. nginx_file_result.stat.exists

示例

root@ubuntu20:~# cat stat.yaml
---
- hosts: db
  remote_user: root
  gather_facts: no

  tasks:
    - name: checkfile
      stat: path=/data/mysql
      register: st
    - name: debug
      debug:
        msg: "/data/mysql is not exist"
      when: not st.stat.exists
root@ubuntu20:~# ansible-playbook stat.yaml

PLAY [db] ********************************************************************************************************************

TASK [checkfile] *************************************************************************************************************
ok: [10.0.0.16]
ok: [10.0.0.15]

TASK [debug] *****************************************************************************************************************
skipping: [10.0.0.16]
ok: [10.0.0.15] => {
    "msg": "/data/mysql is not exist"
}

PLAY RECAP *******************************************************************************************************************
10.0.0.15                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
10.0.0.16                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

root@ubuntu20:~#

unarchive

功能:解包解压缩

实现有两种用法:

  • 1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes,此为默认值,可省略

  • 2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no

常见参数

header 1header 2
copy默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no,
会在远程主机上寻找src源文件
remote_src和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible 主机上
src源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,
如果是远程主机上的路径,则需要设置copy=no
dest远程主机上的目标路径
mode设置解压缩后的文件权限
 
ansible all -m unarchive -a 'src=/data/foo.tgz dest=/var/lib/foo owner=song group=bin'

ansible all -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'

ansible all -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'

ansible websrvs -m unarchive -a 'src=https://releases.ansible.com/ansible/ansible-2.1.6.0-0.1.rc1.tar.gz dest=/data/ owner=root remote_src=yes'

ansible websrvs -m unarchive -a 'src=http://nginx.org/download/nginx-1.18.0.tar.gz dest=/usr/local/src/ copy=no'

Archive 模块

功能:打包压缩保存在被管理节点

示例

ansible websrvs -m archive  -a 'path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=song mode=0600'

Lineinfile 模块

ansible在使用sed进行替换时,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换时, 存在问题,无法正常进行替换 。其实在ansible自身提供了两个模块:lineinfile模块和replace模块,可 以方便的进行替换

一般在ansible当中去修改某个文件的单行进行替换的时候需要使用lineinfile模块

regexp参数 :使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。

如果想进行多行匹配进行替换需要使用replace模块

功能:相当于sed,可以修改文件内容

示例

ansible websrvs -m  lineinfile -a "path=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 80'"

ansible all -m   lineinfile -a "path=/etc/selinux/config regexp='^SELINUX='line='SELINUX=disabled'"

ansible all -m lineinfile  -a 'dest=/etc/fstab state=absent regexp="^#"'

Replace 模块

该模块有点类似于sed命令,主要也是基于正则进行匹配和替换,建议使用

示例

 
ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#\1'"

ansible all -m replace -a "path=/etc/fstab regexp='^#(UUID.*)' replace='\1'"

SELinux 模块

该模块管理 SELInux 策略

示例

root@ubuntu20:~# ansible 10.0.0.11 -m selinux -a 'state=disabled'
10.0.0.11 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "configfile": "/etc/selinux/config",
    "msg": "",
    "policy": "targeted",
    "reboot_required": false,
    "state": "disabled"
}
root@ubuntu20:~#

[root@centos8 ~]#grep -v '#' /etc/selinux/config

SELINUX=disabled
SELINUXTYPE=targeted


[root@centos8 ~]#getenforce
Disabled
[root@centos8 ~]#

reboot 模块

ansible web -m reboot

mount 挂载和卸载

功能: 挂载和卸载文件系统

示例

# 临时挂载
mount web -m mount -a 'src="UUID=b3e48f45-f933-4c8e-a700-22a159ec9077" path=/home fstype=xfs opts=noatime state=present'

# 临时取消挂载
mount web -m mount -a 'path=/home fstype=xfs opts=noatime state=unmounted'

# 永久挂载
ansible web -m mount -a 'src=10.0.0.11:/data/wordpress path=/var/www/html/wp- content/uploads opts="_netdev" state=mounted'

# 永久卸载
ansible web -m mount -a 'src=10.0.0.11:/data/wordpress path=/var/www/html/wp- content/uploads state=absent'
 

debug 模块

此模块可以输出信息

注意: msg后面的变量需要加 " " 引起来

示例

root@ubuntu20:~# ansible db -m debug
10.0.0.16 | SUCCESS => {
    "msg": "Hello world!"
}
10.0.0.15 | SUCCESS => {
    "msg": "Hello world!"
}
root@ubuntu20:~#

示例

root@ubuntu20:~# cat debug.yaml
---
- hosts: db
  remote_user: root
  gather_facts: no

  tasks:
    - name: output hello world
      debug:

# 默认没有指定msg,默认输出"Hello world!"
root@ubuntu20:~# ansible-playbook debug.yaml

PLAY [db] ********************************************************************************************************************

TASK [output hello world] ****************************************************************************************************
ok: [10.0.0.15] => {
    "msg": "Hello world!"
}
ok: [10.0.0.16] => {
    "msg": "Hello world!"
}

PLAY RECAP *******************************************************************************************************************
10.0.0.15                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
10.0.0.16                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

root@ubuntu20:~#

示例:利用 debug 模块输出变量

root@ubuntu20:~# cat debug.yaml
---
- hosts: db
  remote_user: root
  gather_facts: yes

  tasks:
    - name: output variables
      debug:
        msg: HostName "{{ ansible_nodename  }}" IPaddr "{{ ansible_default_ipv4.address }}"
root@ubuntu20:~# ansible-playbook debug.yaml

PLAY [db] ********************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
ok: [10.0.0.16]
ok: [10.0.0.15]

TASK [output variables] ******************************************************************************************************
ok: [10.0.0.15] => {
    "msg": "HostName \"song-VirtualBox\" IPaddr \"172.18.1.125\""
}
ok: [10.0.0.16] => {
    "msg": "HostName \"ubuntu20\" IPaddr \"172.18.1.4\""
}

PLAY RECAP *******************************************************************************************************************
10.0.0.15                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
10.0.0.16                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

root@ubuntu20:~#

注意:此处如果 gather_facts: no 将无法得到变量的值,会报错

root@ubuntu20:~# ansible-playbook debug.yaml

PLAY [db] ********************************************************************************************************************

TASK [output variables] ******************************************************************************************************
fatal: [10.0.0.15]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was:
'ansible_nodename' is undefined\n\nThe error appears to be in '/root/debug.yaml': line 7, column 7, 
but may\nbe elsewhere in the file depending on the exact syntax problem.\n\n
The offending line appears to be:\n\n  tasks:\n    - name: output variables\n      ^ here\n"}
fatal: [10.0.0.16]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was:
'ansible_nodename' is undefined\n\nThe error appears to be in '/root/debug.yaml': line 7, column 7, 
but may\nbe elsewhere in the file depending on the exact syntax problem.\n\n
The offending line appears to be:\n\n  tasks:\n    - name: output variables\n      ^ here\n"}

PLAY RECAP *******************************************************************************************************************
10.0.0.15                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
10.0.0.16                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

root@ubuntu20:~#

示例:显示字符串特定字符

root@ubuntu20:~# cat debug.yaml
---
- hosts: db
  remote_user: root
  gather_facts: no
  vars:
    str: "abcdefg"

  tasks:
  - debug:
      msg: "{{ str[3] }}"
root@ubuntu20:~# ansible-playbook debug.yaml

PLAY [db] ********************************************************************************************************************

TASK [debug] *****************************************************************************************************************
ok: [10.0.0.15] => {
    "msg": "d"
}
ok: [10.0.0.16] => {
    "msg": "d"
}

PLAY RECAP *******************************************************************************************************************
10.0.0.15                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
10.0.0.16                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

root@ubuntu20:~#
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值