Ansible 学习系列
这一节主要介绍ansible的基本概念,常用模块
一、Ansible 介绍
简介
Ansible是一个配置管理系统configuration management system, ansible 是一个基于python 开发的(集合了众多运维工具 puppet、cfengine、chef、func、fabric的优点)自动化运维工具, 其功能实现基于ssh远程连接服务, ansible 可以实现批量系统配置,批量软件部署,批量文件拷贝,批量运行命令等功能, 除了ansible之外,还有salt、chef、puppet 等批量管理工具。
优势
易读的语法:playbook语法基于YAML,YAML是一种以易于人类读写为设计理念的数据格式语言
远程主机无须安装依赖:需要被管理的服务器安装SSH和Python2.5以上版本
基于推送模式:可以直接控制变更在服务器上发生的时间。拉取模式在大规模服务器场景上有较好的扩展性
内置模块:内置大量功能模块,模块具有幂等性的,意味着重复同一个playbook是安全
二、安装ansible及命令文件介绍
Ansible有两种安装方式:yum和pip
Linux环境root用户:
yum install -y ansible
配置文件目录:/etc/ansible/
执行文件目录:/usr/bin/
Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
Help文档目录:/usr/share/doc/ansible-X.X.X/
Man文档目录:/usr/share/man/man1/
pip install ansible
ansible程序文件
/usr/bin/ansible: 命令行工具
ansible命令通用格式: ansible <host-pattern> [options] [-m module_name] [-a args]
/usr/bin/ansible-doc: 帮助文档 ** 重要 **
/usr/bin/ansible-playbook: 剧本执行工具
/etc/ansible/ansible.cfg: 主配置文件
/etc/ansible/hosts: 管理的主机清单
/etc/ansible/roles: 角色存放处
ansible配置文件ansible.cfg
默认配置文件存储在/etc/ansible/ansible.cfg
ansible寻找ansible.cfg的顺序:
1.ANSIBLE_CONFIG环境变量所指定的文件
2…/ansible.cfg当前目录下的ansible.cfg <=======建议和playbook一起,放到当前目录下
3.~/.ansible.cfg 主目录下的.ansible.cfg
4./etc/ansible/ansible.cfg
inventory文件
ansible管理主机的集合称为inventory。inventory文件名称默认为:hosts,也要为以下方式:
存储路径:
/etc/ansible/hosts
/home/
inventory文件常用参数
ansible_ssh_host 将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port ssh端口号.如果不是默认的端口号,通过此变量设置.
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_{xxxx}_interpreter 与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
例如:
[root@kickstart auto]# cat hosts
# install python3 etcd patroni
[test2] <-----组名
192.168.150.190 hostname=pg01 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=root
192.168.150.191 hostname=pg02 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=root
192.168.150.192 hostname=pg03 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=root
playbook文件
playbook是Ansible中一个术语,指的是用于配置管理的脚本。想要运行playbook脚本,可能需要以下文件入目录的支持,以使配置更加灵活,标准。
一个playbook的目录基本结构:最简单的可以只包含两个文件:hosts 与.yml的playbook文件
[root@kickstart enmo]# tree /playbooks/enmo
/root/playbooks/enmo
├── config_hosts.yml <------主playbook
├── files <------文件存放目录
├── group_vars <------组变量目录
├── hosts <------inventory文件
├── host_vars <------主机变量目录
├── roles <------将playbook分为多个文件的机制
└── templates <------模板文件,可传入变量
ansible命令
[root@kickstart ~]# ansible --version
ansible [core 2.12.1]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/python38/lib/python3.8/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/python38/bin/ansible
python version = 3.8.11 (default, Dec 29 2021, 23:25:50) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
jinja version = 3.0.3
libyaml = True
[root@kickstart enmo]# ansible test -m ping
192.168.150.190 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.150.192 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.150.191 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
ansible-playbook命令
在目标主机上运行ansible脚本中定义的任务
play示例:
每个play必须包含以下两项:
hosts: 一组主机
tasks: 需要在这组主机上运行的任务
其余,都是可选项配置:
name: play的注释,运行play时将这段文字打印出来
vars: 一系列变理与值
tasks: play 中运行的任务;每个task必须包含一个键值对。键是块的名字,值是传递到模块的参数
- hosts: test
remote_user: root
vars_files: /root/auto/group_vars/test
tasks:
- debug: msg='{{hostname}}'
- name: copy iso file
copy: src=/root/CentOS-7-x86_64-Everything-1810.iso dest=/root/CentOS-7-x86_64-Everything-1810.iso
- name: Mount DVD read-only
ansible.posix.mount:
path: /mnt
src: /root/CentOS-7-x86_64-Everything-1810.iso
fstype: iso9660
state: mounted
- name : Create a directory if it does not exist
ansible.builtin.file:
path: /etc/yum.repos.d/bak
state: directory
mode: '0755'
- name: This command will change the working directory to somedir/
ansible.builtin.shell:
cmd: mv *.repo bak
chdir: /etc/yum.repos.d
removes: /etc/yum.repos.d/*.repo
- name: scp yum config file
copy: src=/root/auto/centos7.6.repo dest=/etc/yum.repos.d/centos7.6.repo
- name: yum postgresql rpm packages
yum:
name: "{{ packages }}"
vars:
packages:
- ncurses-devel
- gdbm-devel
- openssl-devel
- readline-devel
- zlib-devel
- sqlite-devel
- tk-devel
- xz-devel
- gcc
- python-psycopg2
state: present
ansible_python_interpreter: /usr/bin/python2
ansible-config命令
查看ansible配置信息
[root@kickstart enmo]# ansible-config -h
usage: ansible-config [-h] [--version] [-v] {list,dump,view,init} ...
View ansible configuration.
positional arguments:
{list,dump,view,init}
list Print all config options
dump Dump configuration
view View configuration file
init Create initial configuration
optional arguments:
--version show program's version number, config file location, configured module
search path, module location, executable location and exit
-h, --help show this help message and exit
-v, --verbose verbose mode (-vvv for more, -vvvv to enable connection debugging)
ansible-inventory命令
查看inventory配置信息
[root@kickstart enmo]# ansible-inventory --list
{
"_meta": {
"hostvars": {
"192.168.150.190": {
"ansible_ssh_pass": "root",
"ansible_ssh_port": 22,
"ansible_ssh_user": "root",
"hostname": "pg05"
},
"192.168.150.191": {
"ansible_ssh_pass": "root",
"ansible_ssh_port": 22,
"ansible_ssh_user": "root",
"hostname": "pg05"
},
"192.168.150.192": {
"ansible_ssh_pass": "root",
"ansible_ssh_port": 22,
"ansible_ssh_user": "root",
"hostname": "pg06"
}
}
},
"all": {
"children": [
"test",
"ungrouped"
]
},
"test": {
"hosts": [
"192.168.150.190",
"192.168.150.191",
"192.168.150.192"
]
}
}
ansible-galaxy命令
ansible-galaxy命令用来从ansible社区下载分享的role及生成与role相关的初始文件与目录
[root@kickstart playbooks]# ansible-galaxy init --init-path=/root/playbooks/roles postgresql
- Role postgresql was created successfully
[root@kickstart roles]# ls
postgresql
[root@kickstart roles]# tree postgresql/
postgresql/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
8 directories, 8 files
三、ansible常用模块及使用方法
| 模块名 | 功能 |
|---|---|
| file | 设置文件、链接文件、目录的属性;删除文件、链接文件、目录 |
| lineinfile | 编辑文件单行内容 |
| replace | 编辑文件多行内容 |
| blockinfile | 编辑文件块内容:插入、更新、删除 |
| copy | 将文件从本地或远程复制到远程 |
| fetch | 将文件从远程复制到本地 |
| template | 向远程复制模板文件把变量写入 |
| synchronize | 向远程复制文件,适合比较大的文件 |
| pip | 管理Python lib库文件 |
| yum | Redhat和Centos管理操作系统rpm包 |
| apt | Ubuntu Debian软件包管理工具 |
| yum_repository | 配置yum源 |
| archive | 归档或压缩文件 |
| unarchive | 解压文件 |
| hostname | 设置主机名 |
| user | 管理操作系统账号 |
| group | 管理用户组 |
| shell | 运行被控端系统命令,支持变量与特殊符号 |
| command | 运行被控端系统命令,不支持变理与特殊符号 ,推荐用shell |
| raw | 和shell 类似,用于没有安装python的环境 |
| script | 传输后在远程节点上运行本地脚本 |
| service | 管理远程节点服务 |
| mount | 挂载文件系统,NFS,ISO等 |
| stat | 查看远程文件的状态 |
| get_url | 用于从http ftp https服务器下载文件 |
| fail | 失败模块,一般与stat模块一块用 |
| debug | 用于脚本调试 |
| ping | 查看到目标端是否连通 |
| cron | 定时任务 |
file
file模块主要用于远程主机上的文件操作,file模块包含如下选项:
force: 需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项: yes|no
group: 定义文件/目录的属组
mode: 定义文件/目录的权限
owner: 定义文件/目录的属主
path: 必选项,定义文件/目录的路径
recurse: 递归的设置文件的属性,只对目录有效
src: 要被链接的源文件的路径,只应用于state=link的情况
dest: 被链接到的路径,只应用于state=link的情况
state: 表示file的状态, 主要分为:
directory: 如果目录不存在,创建目录;
file: 即使文件不存在,也不会被创建;
link: 创建软链接;
hard: 创建硬链接;
touch: 如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间;
absent: 删除目录、文件或者取消链接文件;
# 改变文件的属组与权限
- name: Change file ownership, group and permissions
ansible.builtin.file:
path: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
# 给文件授权
- name: Give insecure permissions to an existing file
ansible.builtin.file:
path: /work
owner: root
group: root
mode: '1777'
# 创建软链接文件
- name: Create a symbolic link
ansible.builtin.file:
src: /file/to/link/to
dest: /path/to/symlink
owner: foo
group: foo
state: link
# 使用变量的方式,创建硬链接文件,
- name: Create two hard links
ansible.builtin.file:
src: '/tmp/{{ item.src }}'
dest: '{{ item.dest }}'
state: hard
loop:
- { src: x, dest: y }
- { src: z, dest: k }
# 创建一个文件并授权
- name: Touch a file, using symbolic modes to set the permissions (equivalent to 0644)
ansible.builtin.file:
path: /etc/foo.conf
state: touch
mode: u=rw,g=r,o=r
# 创建文件,并增加权限 与 减少权限
- name: Touch the same file, but add/remove some permissions
ansible.builtin.file:
path: /etc/foo.conf
state: touch
mode: u+rw,g-wx,o-rwx
# 创建相同的文件,不改变时间,使得幂等
- name: Touch again the same file, but do not change times this makes the task idempotent
ansible.builtin.file:
path: /etc/foo.conf
state: touch
mode: u+rw,g-wx,o-rwx
modification_time: preserve
access_time: preserve
# 创建一个目录,如果不存在
- name: Create a directory if it does not exist
ansible.builtin.file:
path: /etc/some_directory
state: directory
mode: '0755'
# 改变文件的修改时间与访问时间
- name: Update modification and access time of given file
ansible.builtin.file:
path: /etc/some_file
state: file
modification_time: now
access_time: now
# 设置文件访问时间
- name: Set access time based on seconds from epoch value
ansible.builtin.file:
path: /etc/another_file
state: file
access_time: '{{ "%Y%m%d%H%M.%S" | strftime(stat_var.stat.atime) }}'
# 迭代改一个目录的属组
- name: Recursively change ownership of a directory
ansible.builtin.file:
path: /etc/foo
state: directory
recurse: yes
owner: foo
group: foo
# 删除一个文件
- name: Remove file (delete file)
ansible.builtin.file:
path: /etc/foo.txt
state: absent
#删除一个目录及子文件
- name: Recursively remove directory
ansible.builtin.file:
path: /etc/foo
state: absent
lineinfile
用于对远程受控节点的文件编辑模块. 主要选项有:
path: 指定要修改的配置文件, 包括:
regexp:匹配要修改的内容
line:要增加或者修改的内容
state: 状态, 包括:
absent:表示删除,当匹配到时进行删除
present:表示增加,当匹配到时进行修改,当没有匹配到时在最后增加一行,默认为此项
backrefs: 该参数值包括:
no:表示如果没有匹配到,则增加line;如果匹配成功,则替换line;
yes:表示如果没有匹配到,则不变line;如果匹配成功,则替换line;
backup: 该参数值包括:
no:表示如果没有匹配到,则增加line;如果匹配成功,则替换line;不备份原文件
yes:表示如果没有匹配到,则增加line;如果匹配成功,则替换line;备份原文件
insertafter(匹配的是此行): 在匹配到的行之后添加一行. (经测试, 发现是匹配到的行的最后一行的后面添加一行)
insertbefore(匹配的是此行): 在匹配到的行之前添加一行. (经测试, 发现是匹配到的行的最后一行的前面添加一行)
温馨提示: 经测试,当不添加backerfs: yes参数时,匹配到后也会进行替换,但当匹配到的内容不存在时,会在最后增加一行;所以当不增加backerfs参数时,要确定匹配到的内容存在;
# NOTE: Before 2.3, option 'dest', 'destfile' or 'name' was used instead of 'path'
- name: Ensure SELinux is set to enforcing mode
ansible.builtin.lineinfile:
path: /etc/selinux/config
regexp: '^SELINUX='
line: SELINUX=enforcing
- name: Make sure group wheel is not in the sudoers configuration
ansible.builtin.lineinfile:
path: /etc/sudoers
state: absent
regexp: '^%wheel'
- name: Replace a localhost entry with our own
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: '^127\.0\.0\.1'
line: 127.0.0.1 localhost
owner: root
group: root
mode: '0644'
- name: Replace a localhost entry searching for a literal string to avoid escaping
lineinfile:
path: /etc/hosts
search_string: '127.0.0.1'
line: 127.0.0.1 localhost
owner: root
group: root
mode: '0644'
- name: Ensure the default Apache port is 8080
ansible.builtin.lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen '
insertafter: '^#Listen '
line: Listen 8080
- name: Ensure php extension matches new pattern
lineinfile:
path: /etc/httpd/conf/httpd.conf
search_string: '<FilesMatch ".php[45]?$">'
insertafter: '^\t<Location \/>\n'
line: ' <FilesMatch ".php[34]?$">'
- name: Ensure we have our own comment added to /etc/services
ansible.builtin.lineinfile:
path: /etc/services
regexp: '^# port for http'
insertbefore: '^www.*80/tcp'
line: '# port for http by default'
- name: Add a line to a file if the file does not exist, without passing regexp
ansible.builtin.lineinfile:
path: /tmp/testfile
line: 192.168.1.99 foo.lab.net foo
create: yes
# NOTE: Yaml requires escaping backslashes in double quotes but not in single quotes
- name: Ensure the JBoss memory settings are exactly as needed
ansible.builtin.lineinfile:
path: /opt/jboss-as/bin/standalone.conf
regexp: '^(.*)Xms(\d+)m(.*)$'
line: '\1Xms${xms}m\3'
backrefs: yes
# NOTE: Fully quoted because of the ': ' on the line. See the Gotchas in the YAML docs.
- name: Validate the sudoers file before saving
ansible.builtin.lineinfile:
path: /etc/sudoers
state: present
regexp: '^%ADMIN ALL='
line: '%ADMIN ALL=(ALL) NOPASSWD: ALL'
validate: /usr/sbin/visudo -cf %s
# See https://docs.python.org/3/library/re.html for further details on syntax
- name: Use backrefs with alternative group syntax to avoid conflicts with variable values
ansible.builtin.lineinfile:
path: /tmp/config
regexp: ^(host=).*
line: \g<1>{{ hostname }}
backrefs: yes
replace
- name: Before Ansible 2.3, option 'dest', 'destfile' or 'name' was used instead of 'path'
ansible.builtin.replace:
path: /etc/hosts
regexp: '(\s+)old\.host\.name(\s+.*)?$'
replace: '\1new.host.name\2'
- name: Replace after the expression till the end of the file (requires Ansible >= 2.4)
ansible.builtin.replace:
path: /etc/apache2/sites-available/default.conf
after: 'NameVirtualHost [*]'
regexp: '^(.+)$'
replace: '# \1'
- name: Replace before the expression till the begin of the file (requires Ansible >= 2.4)
ansible.builtin.replace:
path: /etc/apache2/sites-available/default.conf
before: '# live site config'
regexp: '^(.+)$'
replace: '# \1'
# Prior to Ansible 2.7.10, using before and after in combination did the opposite of what was intended.
# see https://github.com/ansible/ansible/issues/31354 for details.
- name: Replace between the expressions (requires Ansible >= 2.4)
ansible.builtin.replace:
path: /etc/hosts
after: '<VirtualHost [*]>'
before: '</VirtualHost>'
regexp: '^(.+)$'
replace: '# \1'
- name: Supports common file attributes
ansible.builtin.replace:
path: /home/jdoe/.ssh/known_hosts
regexp: '^old\.host\.name[^\n]*\n'
owner: jdoe
group: jdoe
mode: '0644'
- name: Supports a validate command
ansible.builtin.replace:
path: /etc/apache/ports
regexp: '^(NameVirtualHost|Listen)\s+80\s*$'
replace: '\1 127.0.0.1:8080'
validate: '/usr/sbin/apache2ctl -f %s -t'
- name: Short form task (in ansible 2+) necessitates backslash-escaped sequences
ansible.builtin.replace: path=/etc/hosts regexp='\\b(localhost)(\\d*)\\b' replace='\\1\\2.localdomain\\2 \\1\\2'
- name: Long form task does not
ansible.builtin.replace:
path: /etc/hosts
regexp: '\b(localhost)(\d*)\b'
replace: '\1\2.localdomain\2 \1\2'
- name: Explicitly specifying positional matched groups in replacement
ansible.builtin.replace:
path: /etc/ssh/sshd_config
regexp: '^(ListenAddress[ ]+)[^\n]+$'
replace: '\g<1>0.0.0.0'
- name: Explicitly specifying named matched groups
ansible.builtin.replace:
path: /etc/ssh/sshd_config
regexp: '^(?P<dctv>ListenAddress[ ]+)(?P<host>[^\n]+)$'
replace: '#\g<dctv>\g<host>\n\g<dctv>0.0.0.0'
copy
把主控节点本地的文件上传同步到远程受控节点上, 该模块不支持从远程受控节点拉取文件到主控节点上。
参数选项如下:
**src:**指定源文件路径,可以是相对路径,也可以是绝对路径,可以是目录(并非是必须的,可以使用content,直接生成文件内容). src即是要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用”/”来结尾,则只复制目录里的内容,如果没有使用”/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync。
**dest:**指定目标文件路径,只能是绝对路径,如果src是目录,此项必须是目录. 这个是必选项!
**owner:**指定属主;
**group:**指定属组;
**mode:**指定权限,可以以数字指定比如0644;
**content:**代替src,直接往dest文件中写内容,可以引用变量,也可以直接使用inventory中的主机变量. 写后会覆盖原文件内容!
**backup:**在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no
force: 如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes ;
**directory_mode:**递归的设定目录的权限,默认为系统默认权限;
**others:**所有的file模块里的选项都可以在这里使用;
特别注意: src和content不能同时使用!!!
- name: Copy file with owner and permissions
ansible.builtin.copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
- name: Copy file with owner and permission, using symbolic representation
ansible.builtin.copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: u=rw,g=r,o=r
- name: Another symbolic mode example, adding some permissions and removing others
ansible.builtin.copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: u+rw,g-wx,o-rwx
- name: Copy a new "ntp.conf" file into place, backing up the original if it differs from the copied version
ansible.builtin.copy:
src: /mine/ntp.conf
dest: /etc/ntp.conf
owner: root
group: root
mode: '0644'
backup: yes
- name: Copy a new "sudoers" file into place, after passing validation with visudo
ansible.builtin.copy:
src: /mine/sudoers
dest: /etc/sudoers
validate: /usr/sbin/visudo -csf %s
- name: Copy a "sudoers" file on the remote machine for editing
ansible.builtin.copy:
src: /etc/sudoers
dest: /etc/sudoers.edit
remote_src: yes
validate: /usr/sbin/visudo -csf %s
- name: Copy using inline content
ansible.builtin.copy:
content: '# This file was moved to /etc/other.conf'
dest: /etc/mine.conf
- name: If follow=yes, /path/to/file will be overwritten by contents of foo.conf
ansible.builtin.copy:
src: /etc/foo.conf
dest: /path/to/link # link to /path/to/file
follow: yes
- name: If follow=no, /path/to/link will become a file and be overwritten by contents of foo.conf
ansible.builtin.copy:
src: /etc/foo.conf
dest: /path/to/link # link to /path/to/file
follow: no
fetch
- name: Store file into /tmp/fetched/host.example.com /tmp/somefile
ansible.builtin.fetch:
src: /tmp/somefile
dest: /tmp/fetched
- name: Specifying a path directly
ansible.builtin.fetch:
src: /tmp/somefile
dest: /tmp/prefix-{{ inventory_hostname }}
flat: yes
- name: Specifying a destination path
ansible.builtin.fetch:
src: /tmp/uniquefile
dest: /tmp/special/
flat: yes
- name: Storing in a path relative to the playbook
ansible.builtin.fetch:
src: /tmp/uniquefile
dest: special/prefix-{{ inventory_hostname }}
flat: yes
template
基于模板方式生成一个文件复制到远程主机(template使用Jinjia2格式作为文件模版,进行文档内变量的替换的模块。每次使用都会被ansible标记为”changed”状态。)
backup: 如果原目标文件存在,则先备份目标文件
src: 在ansible控制器上的Jinja2格式化模板的路径。 这可以是相对或绝对的路径。
dest: 将模板渲染到远程机器上的位置。
force: 是否强制覆盖,默认为yes
owner: 目标文件属主
group: 目标文件属组
mode: 目标文件的权限模式,模式可以被指定为符号模式(例如,u + rwx或u = rw,g = r,o = r)
- name: Template a file to /etc/file.conf
ansible.builtin.template:
src: /mytemplates/foo.j2
dest: /etc/file.conf
owner: bin
group: wheel
mode: '0644'
- name: Template a file, using symbolic modes (equivalent to 0644)
ansible.builtin.template:
src: /mytemplates/foo.j2
dest: /etc/file.conf
owner: bin
group: wheel
mode: u=rw,g=r,o=r
- name: Copy a version of named.conf that is dependent on the OS. setype obtained by doing ls -Z /etc/named.conf on original file
ansible.builtin.template:
src: named.conf_{{ ansible_os_family }}.j2
dest: /etc/named.conf
group: named
setype: named_conf_t
mode: 0640
- name: Create a DOS-style text file from a template
ansible.builtin.template:
src: config.ini.j2
dest: /share/windows/config.ini
newline_sequence: '\r\n'
- name: Copy a new sudoers file into place, after passing validation with visudo
ansible.builtin.template:
src: /mine/sudoers
dest: /etc/sudoers
validate: /usr/sbin/visudo -cf %s
- name: Update sshd configuration safely, avoid locking yourself out
ansible.builtin.template:
src: etc/ssh/sshd_config.j2
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: '0600'
validate: /usr/sbin/sshd -t -f %s
backup: yes
synchronize
这个模块是使用rsync同步文件,将主控方目录推送到指定受控节点的目录下。
其参数如下:
delete: 删除不存在的文件,delete=yes 使两边的内容一样(即以推送方为主),默认no
src: 要同步到目的地的源主机上的路径; 路径可以是绝对的或相对的。如果路径使用”/”来结尾,则只复制目录里的内容,如果没有使用”/”来结尾,则包含目录在内的整个内容全部复制
**dest:**目的地主机上将与源同步的路径; 路径可以是绝对的或相对的。
**dest_port:**默认目录主机上的端口 ,默认是22,走的ssh协议。
mode: push或pull,默认push,一般用于从本机向远程主机上传文件,pull 模式用于从远程主机上取文件。
**rsync_opts:**通过传递数组来指定其他rsync选项。
- name: Synchronization of src on the control machine to dest on the remote hosts
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
- name: Synchronization using rsync protocol (push)
ansible.posix.synchronize:
src: some/relative/path/
dest: rsync://somehost.com/path/
- name: Synchronization using rsync protocol (pull)
ansible.posix.synchronize:
mode: pull
src: rsync://somehost.com/path/
dest: /some/absolute/path/
- name: Synchronization using rsync protocol on delegate host (push)
ansible.posix.synchronize:
src: /some/absolute/path/
dest: rsync://somehost.com/path/
delegate_to: delegate.host
- name: Synchronization using rsync protocol on delegate host (pull)
ansible.posix.synchronize:
mode: pull
src: rsync://somehost.com/path/
dest: /some/absolute/path/
delegate_to: delegate.host
- name: Synchronization without any --archive options enabled
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
archive: no
- name: Synchronization with --archive options enabled except for --recursive
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
recursive: no
- name: Synchronization with --archive options enabled except for --times, with --checksum option enabled
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
checksum: yes
times: no
- name: Synchronization without --archive options enabled except use --links
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
archive: no
links: yes
- name: Synchronization of two paths both on the control machine
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
delegate_to: localhost
- name: Synchronization of src on the inventory host to the dest on the localhost in pull mode
ansible.posix.synchronize:
mode: pull
src: some/relative/path
dest: /some/absolute/path
- name: Synchronization of src on delegate host to dest on the current inventory host.
ansible.posix.synchronize:
src: /first/absolute/path
dest: /second/absolute/path
delegate_to: delegate.host
- name: Synchronize two directories on one remote host.
ansible.posix.synchronize:
src: /first/absolute/path
dest: /second/absolute/path
delegate_to: "{{ inventory_hostname }}"
- name: Synchronize and delete files in dest on the remote host that are not found in src of localhost.
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
delete: yes
recursive: yes
# This specific command is granted su privileges on the destination
- name: Synchronize using an alternate rsync command
ansible.posix.synchronize:
src: some/relative/path
dest: /some/absolute/path
rsync_path: su -c rsync
# Example .rsync-filter file in the source directory
# - var # exclude any path whose last part is 'var'
# - /var # exclude any path starting with 'var' starting at the source directory
# + /var/conf # include /var/conf even though it was previously excluded
- name: Synchronize passing in extra rsync options
ansible.posix.synchronize:
src: /tmp/helloworld
dest: /var/www/helloworld
rsync_opts:
- "--no-motd"
- "--exclude=.git"
# Hardlink files if they didn't change
- name: Use hardlinks when synchronizing filesystems
ansible.posix.synchronize:
src: /tmp/path_a/foo.txt
dest: /tmp/path_b/foo.txt
link_dest: /tmp/path_a/
# Specify the rsync binary to use on remote host and on local host
- hosts: groupofhosts
vars:
ansible_rsync_path: /usr/gnu/bin/rsync
tasks:
- name: copy /tmp/localpath/ to remote location /tmp/remotepath
ansible.posix.synchronize:
src: /tmp/localpath/
dest: /tmp/remotepath
rsync_path: /usr/gnu/bin/rsync
将主控节点上/data/kevin目录同步到受控节点的/home目录下
ansible web-nodes -m synchronize -a 'src=/data/kevin dest=/home'
将主控节点上/data/kevin/test.file文件同步到受控节点的/opt目录下
ansible web-nodes -m synchronize -a 'src=/data/kevin/test.file dest=/opt'
将主控节点上/data/kevin/test.file文件同步到受控节点的/root/bobo.file文件
ansible web-nodes -m synchronize -a 'src=/data/kevin/test.file dest=/root/bobo.file'
将主控节点上/opt/同步到受控节点的/opt/目录, 使受控节点保持和主控节点的opt目录一致, 不一样的就删除! 默认delete=no
ansible web-nodes -m synchronize -a 'src=/opt/ dest=/opt/ delete=yes'
注意命令中要加"/", 如果不加"/", 则主控节点的opt目录就同步到受控节点的/opt目录下即, 即/opt/opt
ansible web-nodes -m synchronize -a 'src=/opt dest=/opt delete=yes'
将主控节点上/data/kevin目录同步到受控节点的/mnt/www目录下. 但是bobo目录排除在外! rsync_opts可以进行多次传递.
ansible web-nodes -m synchronize -a 'src=/data/kevin/ dest=/mnt/www/ rsync_opts="--no-motd" rsync_opts="--exclude=bobo"'
强制两边同步保持一致! 跟主控节点源目录保持一致!
ansible web-nodes -m synchronize -a 'src=/data/kevin/ dest=/mnt/www/ rsync_opts="--no-motd" rsync_opts="--exclude=bobo" delete=yes'
从远程受控节点上将/usr/local/src/grace.file文件拉取到主控节点的/root目录下
ansible web-nodes -m synchronize -a 'src=/usr/local/src/grace.file dest=/root/ rsync_opts="-avpgolr" mode=pull '
pip
用于管理Python库依赖项,为了使用pip模块,必须提供参数name或者requirements
chdir: 执行pip命令前cd进入的目录
**name:**要安装的Python库的名称或远程包的URL。
**requirements:**一个pip requirements.txt文件的路径,它应该是远程系统的本地文件,如果使用chdir选项,则可以将文件指定为相对路径。
**version:**指定的Python库的安装版本。
**extra_args:**额外的参数传递给pip (后面使用双引号)。
**executable:**显式可执行文件或可执行文件的路径名,用于为系统中安装的特定版本的Python运行pip。 例如pip-3.3,如果系统中安装了Python 2.7和3.3,并且想要为Python 3.3安装运行pip。 它不能与“virtualenv”参数一起指定(在2.1中添加)。 默认情况下,它将采用适用于python解释器的版本。 pip3在python 3上,pip2或pip在python 2上。
**virtualenv:**要安装到的virtualenv目录的可选路径。 它不能与’executable’参数一起指定(在2.1中添加)。 如果virtualenv不存在,则将在安装软件包之前创建它。 可选的virtualenv_site_packages,virtualenv_command和virtualenv_python选项会影响virtualenv的创建。
**virtualenv_command:**用于创建虚拟环境的命令或路径名。 例如pyvenv,virtualenv,virtualenv2,~/bin /virtualenv,/usr/local/bin/virtualenv。
**virtualenv_python:**用于创建虚拟环境的Python可执行文件。 例如python3.5,python2.7。 未指定时,将使用用于运行ansible模块的Python版本。 当virtualenv_command使用pyvenv或-m venv模块时,不应使用此参数。
**state:**状态(present,absent,latest, forcereinstall),表示是安装还是卸载的状态. 其中present表示默认安装; lastest表示最新版本安装; absent表示卸载和删除; forcereinstall表示强制重新安装, "forcereinstall"选项仅适用于可ansible 2.1及更高版本.
- name: Install bottle python package
pip:
name: bottle
- name: Install bottle python package on version 0.11
pip:
name: bottle==0.11
- name: Install bottle python package with version specifiers
pip:
name: bottle>0.10,<0.20,!=0.11
- name: Install multi python packages with version specifiers
pip:
name:
- django>1.11.0,<1.12.0
- bottle>0.10,<0.20,!=0.11
- name: Install python package using a proxy
# Pip doesn't use the standard environment variables, please use the CAPITALIZED ones below
pip:
name: six
environment:
HTTP_PROXY: '127.0.0.1:8080'
HTTPS_PROXY: '127.0.0.1:8080'
# You do not have to supply '-e' option in extra_args
- name: Install MyApp using one of the remote protocols (bzr+,hg+,git+,svn+)
pip:
name: svn+http://myrepo/svn/MyApp#egg=MyApp
- name: Install MyApp using one of the remote protocols (bzr+,hg+,git+)
pip:
name: git+http://myrepo/app/MyApp
- name: Install MyApp from local tarball
pip:
name: file:///path/to/MyApp.tar.gz
- name: Install bottle into the specified (virtualenv), inheriting none of the globally installed modules
pip:
name: bottle
virtualenv: /my_app/venv
- name: Install bottle into the specified (virtualenv), inheriting globally installed modules
pip:
name: bottle
virtualenv: /my_app/venv
virtualenv_site_packages: yes
- name: Install bottle into the specified (virtualenv), using Python 2.7
pip:
name: bottle
virtualenv: /my_app/venv
virtualenv_command: virtualenv-2.7
- name: Install bottle within a user home directory
pip:
name: bottle
extra_args: --user
- name: Install specified python requirements
pip:
requirements: /my_app/requirements.txt
- name: Install specified python requirements in indicated (virtualenv)
pip:
requirements: /my_app/requirements.txt
virtualenv: /my_app/venv
- name: Install specified python requirements and custom Index URL
pip:
requirements: /my_app/requirements.txt
extra_args: -i https://example.com/pypi/simple
- name: Install specified python requirements offline from a local directory with downloaded packages
pip:
requirements: /my_app/requirements.txt
extra_args: "--no-index --find-links=file:///my_downloaded_packages_dir"
- name: Install bottle for Python 3.3 specifically, using the 'pip3.3' executable
pip:
name: bottle
executable: pip3.3
- name: Install bottle, forcing reinstallation if it's already installed
pip:
name: bottle
state: forcereinstall
- name: Install bottle while ensuring the umask is 0022 (to ensure other users can use it)
pip:
name: bottle
umask: "0022"
become: True
yum
这个模块是RedHat 和 CentOS作为远端受控节点OS的时候,用的最多的模块, 是RedHat / CentOS包管理工具的模块, 使用`yum’软件包管理器管理软件包,其选项有:
**config_file:**yum的配置文件 (optional)
**disable_gpg_check:**关闭gpg_check (optional)
**disablerepo:**不启用某个源 (optional)
**enablerepo:**启用某个源(optional)
**name:**要进行操作的软件包的名字,默认最新的程序包,指明要安装的程序包,可以带上版本号,也可以传递一个url或者一个本地的rpm包的路径
**state:**表示是安装还是卸载的状态,
**其中present、installed、latest 表示安装, **
**absent 、removed表示卸载删除; **
**present默认状态, **
laster表示安装最新版本.
- name: Install the latest version of Apache
yum:
name: httpd
state: latest
- name: Install Apache >= 2.4
yum:
name: httpd>=2.4
state: present
- name: Install a list of packages (suitable replacement for 2.11 loop deprecation warning)
yum:
name:
- nginx
- postgresql
- postgresql-server
state: present
- name: Install a list of packages with a list variable
yum:
name: "{{ packages }}"
vars:
packages:
- httpd
- httpd-tools
- name: Remove the Apache package
yum:
name: httpd
state: absent
- name: Install the latest version of Apache from the testing repo
yum:
name: httpd
enablerepo: testing
state: present
- name: Install one specific version of Apache
yum:
name: httpd-2.2.29-1.4.amzn1
state: present
- name: Upgrade all packages
yum:
name: '*'
state: latest
- name: Upgrade all packages, excluding kernel & foo related packages
yum:
name: '*'
state: latest
exclude: kernel*,foo*
- name: Install the nginx rpm from a remote repo
yum:
name: http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
state: present
- name: Install nginx rpm from a local file
yum:
name: /usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm
state: present
- name: Install the 'Development tools' package group
yum:
name: "@Development tools"
state: present
- name: Install the 'Gnome desktop' environment group
yum:
name: "@^gnome-desktop-environment"
state: present
- name: List ansible packages and register result to print with debug later
yum:
list: ansible
register: result
- name: Install package with multiple repos enabled
yum:
name: sos
enablerepo: "epel,ol7_latest"
- name: Install package with multiple repos disabled
yum:
name: sos
disablerepo: "epel,ol7_latest"
- name: Download the nginx package but do not install it
yum:
name:
- nginx
state: latest
download_only: true
yum_repository
- name: Add repository
yum_repository:
name: epel
description: EPEL YUM repo
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
- 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
# Handler showing how to clean yum metadata cache
- name: yum-clean-metadata
command: yum clean metadata
args:
warn: no
# Example removing a repository and cleaning up metadata cache
- name: Remove repository (and clean up left-over metadata)
yum_repository:
name: epel
state: absent
notify: yum-clean-metadata
- name: Remove repository from a specific repo file
yum_repository:
name: epel
file: external_repos
state: absent
apt
这个模块是ubuntu作为远端受控节点OS的时候,用的最多的模块。Apt是Ubuntu/Debian的包管理工具。
deb: 用于安装远程机器上的.deb后缀的软件包(optional)
install_recommends: 这个参数可以控制远程电脑上是否只是下载软件包,还是下载后安装,默认参数为true,设置为false的时候只下载软件包,不安装
update_cache: 当这个参数为yes的时候等于apt-get update(optional)
name: apt要下载的软件包名字,支持name=git=1.6 这种制定版本的模式
state: 状态(present,absent,latest),表示是安装还是卸载. 其中present、installed、latest 表示安装, absent 、removed表示卸载删除; present默认状态, laster表示安装最新版本.
- name: Install apache httpd (state=present is optional)
apt:
name: apache2
state: present
- name: Update repositories cache and install "foo" package
apt:
name: foo
update_cache: yes
- name: Remove "foo" package
apt:
name: foo
state: absent
- name: Install the package "foo"
apt:
name: foo
- name: Install a list of packages
apt:
pkg:
- foo
- foo-tools
- name: Install the version '1.00' of package "foo"
apt:
name: foo=1.00
- name: Update the repository cache and update package "nginx" to latest version using default release squeeze-backport
apt:
name: nginx
state: latest
default_release: squeeze-backports
update_cache: yes
- name: Install the version '1.18.0' of package "nginx" and allow potential downgrades
apt:
name: nginx=1.18.0
state: present
allow_downgrade: yes
- name: Install zfsutils-linux with ensuring conflicted packages (e.g. zfs-fuse) will not be removed.
apt:
name: zfsutils-linux
state: latest
fail_on_autoremove: yes
- name: Install latest version of "openjdk-6-jdk" ignoring "install-recommends"
apt:
name: openjdk-6-jdk
state: latest
install_recommends: no
- name: Update all packages to their latest version
apt:
name: "*"
state: latest
- name: Upgrade the OS (apt-get dist-upgrade)
apt:
upgrade: dist
- name: Run the equivalent of "apt-get update" as a separate step
apt:
update_cache: yes
- name: Only run "update_cache=yes" if the last one is more than 3600 seconds ago
apt:
update_cache: yes
cache_valid_time: 3600
- name: Pass options to dpkg on run
apt:
upgrade: dist
update_cache: yes
dpkg_options: 'force-confold,force-confdef'
- name: Install a .deb package
apt:
deb: /tmp/mypackage.deb
- name: Install the build dependencies for package "foo"
apt:
pkg: foo
state: build-dep
- name: Install a .deb package from the internet
apt:
deb: https://example.com/python-ppq_0.1-1_all.deb
- name: Remove useless packages from the cache
apt:
autoclean: yes
- name: Remove dependencies that are no longer required
apt:
autoremove: yes
archive
- name: Compress directory /path/to/foo/ into /path/to/foo.tgz
community.general.archive:
path: /path/to/foo
dest: /path/to/foo.tgz
- name: Compress regular file /path/to/foo into /path/to/foo.gz and remove it
community.general.archive:
path: /path/to/foo
remove: yes
- name: Create a zip archive of /path/to/foo
community.general.archive:
path: /path/to/foo
format: zip
- name: Create a bz2 archive of multiple files, rooted at /path
community.general.archive:
path:
- /path/to/foo
- /path/wong/foo
dest: /path/file.tar.bz2
format: bz2
- name: Create a bz2 archive of a globbed path, while excluding specific dirnames
community.general.archive:
path:
- /path/to/foo/*
dest: /path/file.tar.bz2
exclude_path:
- /path/to/foo/bar
- /path/to/foo/baz
format: bz2
- name: Create a bz2 archive of a globbed path, while excluding a glob of dirnames
community.general.archive:
path:
- /path/to/foo/*
dest: /path/file.tar.bz2
exclude_path:
- /path/to/foo/ba*
format: bz2
- name: Use gzip to compress a single archive (i.e don't archive it first with tar)
community.general.archive:
path: /path/to/foo/single.file
dest: /path/file.gz
format: gz
- name: Create a tar.gz archive of a single file.
community.general.archive:
path: /path/to/foo/single.file
dest: /path/file.tar.gz
format: gz
force_archive: true
unarchive
用于解压文件,模块包含如下选项:
copy: 在解压文件之前,是否先将文件复制到远程主机,默认为yes。若为no,则要求目标主机上压缩包必须存在。
creates: 指定一个文件名,当该文件存在时,则解压指令不执行
dest: 远程主机上的一个路径,即文件解压的绝对路径。 必须是一个目录路径!
group: 解压后的目录或文件的属组;
list_files: 如果为yes,则会列出压缩包里的文件,默认为no,2.0版本新增的选项;
mode: 解压后文件的权限;
src: 如果copy为yes,则需要指定压缩文件的源路径;
owner: 解压后文件或目录的属主;
- name: Extract foo.tgz into /var/lib/foo
ansible.builtin.unarchive:
src: foo.tgz
dest: /var/lib/foo
- name: Unarchive a file that is already on the remote machine
ansible.builtin.unarchive:
src: /tmp/foo.zip
dest: /usr/local/bin
remote_src: yes
- name: Unarchive a file that needs to be downloaded (added in 2.0)
ansible.builtin.unarchive:
src: https://example.com/example.zip
dest: /usr/local/bin
remote_src: yes
- name: Unarchive a file with extra options
ansible.builtin.unarchive:
src: /tmp/foo.zip
dest: /usr/local/bin
extra_opts:
- --transform
- s/^xxx/yyy/
hostname
- name: Set a hostname
ansible.builtin.hostname:
name: web01
- name: Set a hostname specifying strategy
ansible.builtin.hostname:
name: web01
use: systemd
user
- name: Add the user 'johnd' with a specific uid and a primary group of 'admin'
ansible.builtin.user:
name: johnd
comment: John Doe
uid: 1040
group: admin
- name: Add the user 'james' with a bash shell, appending the group 'admins' and 'developers' to the user's groups
ansible.builtin.user:
name: james
shell: /bin/bash
groups: admins,developers
append: yes
- name: Remove the user 'johnd'
ansible.builtin.user:
name: johnd
state: absent
remove: yes
- name: Create a 2048-bit SSH key for user jsmith in ~jsmith/.ssh/id_rsa
ansible.builtin.user:
name: jsmith
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
- name: Added a consultant whose account you want to expire
ansible.builtin.user:
name: james18
shell: /bin/zsh
groups: developers
expires: 1422403387
- name: Starting at Ansible 2.6, modify user, remove expiry time
ansible.builtin.user:
name: james18
expires: -1
- name: Set maximum expiration date for password
user:
name: ram19
password_expire_max: 10
- name: Set minimum expiration date for password
user:
name: pushkar15
password_expire_min: 5
group
- name: Ensure group "somegroup" exists
ansible.builtin.group:
name: somegroup
state: present
- name: Ensure group "docker" exists with correct gid
ansible.builtin.group:
name: docker
state: present
gid: 1750
shell
- name: Execute the command in remote shell; stdout goes to the specified file on the remote
ansible.builtin.shell: somescript.sh >> somelog.txt
- name: Change the working directory to somedir/ before executing the command
ansible.builtin.shell: somescript.sh >> somelog.txt
args:
chdir: somedir/
# You can also use the 'args' form to provide the options.
- name: This command will change the working directory to somedir/ and will only run when somedir/somelog.txt doesn't exist
ansible.builtin.shell: somescript.sh >> somelog.txt
args:
chdir: somedir/
creates: somelog.txt
# You can also use the 'cmd' parameter instead of free form format.
- name: This command will change the working directory to somedir/
ansible.builtin.shell:
cmd: ls -l | grep log
chdir: somedir/
- name: Run a command that uses non-posix shell-isms (in this example /bin/sh doesn't handle redirection and wildcards together but bash does)
ansible.builtin.shell: cat < /tmp/*txt
args:
executable: /bin/bash
- name: Run a command using a templated variable (always use quote filter to avoid injection)
ansible.builtin.shell: cat {{ myfile|quote }}
# You can use shell to run other executables to perform actions inline
- name: Run expect to wait for a successful PXE boot via out-of-band CIMC
ansible.builtin.shell: |
set timeout 300
spawn ssh admin@{{ cimc_host }}
expect "password:"
send "{{ cimc_password }}\n"
expect "\n{{ cimc_name }}"
send "connect host\n"
expect "pxeboot.n12"
send "\n"
exit 0
args:
executable: /usr/bin/expect
delegate_to: localhost
# Disabling warnings
- name: Using curl to connect to a host via SOCKS proxy (unsupported in uri). Ordinarily this would throw a warning
ansible.builtin.shell: curl --socks5 localhost:9000 http://www.ansible.com
args:
warn: no
command
- name: Return motd to registered var
ansible.builtin.command: cat /etc/motd
register: mymotd
# free-form (string) arguments, all arguments on one line
- name: Run command if /path/to/database does not exist (without 'args')
ansible.builtin.command: /usr/bin/make_database.sh db_user db_name creates=/path/to/database
# free-form (string) arguments, some arguments on separate lines with the 'args' keyword
# 'args' is a task keyword, passed at the same level as the module
- name: Run command if /path/to/database does not exist (with 'args' keyword)
ansible.builtin.command: /usr/bin/make_database.sh db_user db_name
args:
creates: /path/to/database
# 'cmd' is module parameter
- name: Run command if /path/to/database does not exist (with 'cmd' parameter)
ansible.builtin.command:
cmd: /usr/bin/make_database.sh db_user db_name
creates: /path/to/database
- name: Change the working directory to somedir/ and run the command as db_owner if /path/to/database does not exist
ansible.builtin.command: /usr/bin/make_database.sh db_user db_name
become: yes
become_user: db_owner
args:
chdir: somedir/
creates: /path/to/database
# argv (list) arguments, each argument on a separate line, 'args' keyword not necessary
# 'argv' is a parameter, indented one level from the module
- name: Use 'argv' to send a command as a list - leave 'command' empty
ansible.builtin.command:
argv:
- /usr/bin/make_database.sh
- Username with whitespace
- dbname with whitespace
creates: /path/to/database
- name: Safely use templated variable to run command. Always use the quote filter to avoid injection issues
ansible.builtin.command: cat {{ myfile|quote }}
register: myoutput
raw
执行原始的命令,而不是通过模块子系统。在任何情况下,使用shell或command命令模块也是合适的。
给定原始的参数直接通过配置的远程shell运行。可返回标准输出、错误输出和返回代码。此模块没有变更处理程序支持。 这个模块不需要远程系统上的Python,就像脚本模块一样。此模块也支持Windows目标。raw, shell, command三个模块都能调用对象机器上的某条指令或者某个可执行文件。raw和shell模块很像, 都支持管道; command模块不支持管道。
- name: Bootstrap a host without python2 installed
raw: dnf install -y python2 python2-dnf libselinux-python
- name: Run a command that uses non-posix shell-isms (in this example /bin/sh doesn't handle redirection and wildcards together but bash does)
raw: cat < /tmp/*txt
args:
executable: /bin/bash
- name: Safely use templated variables. Always use quote filter to avoid injection issues.
raw: "{{ package_mgr|quote }} {{ pkg_flags|quote }} install {{ python|quote }}"
- name: List user accounts on a Windows system
raw: Get-WmiObject -Class Win32_UserAccount
script
- name: Run a script with arguments (free form)
ansible.builtin.script: /some/local/script.sh --some-argument 1234
- name: Run a script with arguments (using 'cmd' parameter)
ansible.builtin.script:
cmd: /some/local/script.sh --some-argument 1234
- name: Run a script only if file.txt does not exist on the remote node
ansible.builtin.script: /some/local/create_file.sh --some-argument 1234
args:
creates: /the/created/file.txt
- name: Run a script only if file.txt exists on the remote node
ansible.builtin.script: /some/local/remove_file.sh --some-argument 1234
args:
removes: /the/removed/file.txt
- name: Run a script using an executable in a non-system path
ansible.builtin.script: /some/local/script
args:
executable: /some/remote/executable
- name: Run a script using an executable in a system path
ansible.builtin.script: /some/local/script.py
args:
executable: python3
service
管理服务的模块, service管理的服务必须是yum安装的服务, 即默认的系统服务脚本. 编译安装的服务不好使用service模块管理.
name: 服务名称;
state: started/stopped/restarted/reloaded;
enabled: true/false;
runlevel: 运行级别;
sleep: 如果执行了restarted,在stop和start之间沉睡几秒;
arguments: 给命令行提供一些选项;
- name: Start service httpd, if not started
ansible.builtin.service:
name: httpd
state: started
- name: Stop service httpd, if started
ansible.builtin.service:
name: httpd
state: stopped
- name: Restart service httpd, in all cases
ansible.builtin.service:
name: httpd
state: restarted
- name: Reload service httpd, in all cases
ansible.builtin.service:
name: httpd
state: reloaded
- name: Enable service httpd, and not touch the state
ansible.builtin.service:
name: httpd
enabled: yes
- name: Start service foo, based on running process /usr/bin/foo
ansible.builtin.service:
name: foo
pattern: /usr/bin/foo
state: started
- name: Restart network service for interface eth0
ansible.builtin.service:
name: network
state: restarted
args: eth0
mount
在远程受控节点上挂载文件系统。可用参数:
present: 开机挂载,仅将挂载配置写入/etc/fstab(不常用)
mounted: 挂载设备,并将配置写入/etc/fstab
unmounted: 卸载设备,不会清除/etc/fstab写入的配置
absent: 卸载设备,会清理/etc/fstab写入的配置
# Before 2.3, option 'name' was used instead of 'path'
- name: Mount DVD read-only
ansible.posix.mount:
path: /mnt/dvd
src: /dev/sr0
fstype: iso9660
opts: ro,noauto
state: present
- name: Mount up device by label
ansible.posix.mount:
path: /srv/disk
src: LABEL=SOME_LABEL
fstype: ext4
state: present
- name: Mount up device by UUID
ansible.posix.mount:
path: /home
src: UUID=b3e48f45-f933-4c8e-a700-22a159ec9077
fstype: xfs
opts: noatime
state: present
- name: Unmount a mounted volume
ansible.posix.mount:
path: /tmp/mnt-pnt
state: unmounted
- name: Remount a mounted volume
ansible.posix.mount:
path: /tmp/mnt-pnt
state: remounted
# The following will not save changes to fstab, and only be temporary until
# a reboot, or until calling "state: unmounted" followed by "state: mounted"
# on the same "path"
- name: Remount a mounted volume and append exec to the existing options
ansible.posix.mount:
path: /tmp
state: remounted
opts: exec
- name: Mount and bind a volume
ansible.posix.mount:
path: /system/new_volume/boot
src: /boot
opts: bind
state: mounted
fstype: none
- name: Mount an NFS volume
ansible.posix.mount:
src: 192.168.1.100:/nfs/ssd/shared_data
path: /mnt/shared_data
opts: rw,sync,hard,intr
state: mounted
fstype: nfs
- name: Mount NFS volumes with noauto according to boot option
ansible.posix.mount:
src: 192.168.1.100:/nfs/ssd/shared_data
path: /mnt/shared_data
opts: rw,sync,hard,intr
boot: no
state: mounted
fstype: nfs
stat
# Obtain the stats of /etc/foo.conf, and check that the file still belongs
# to 'root'. Fail otherwise.
- name: Get stats of a file
ansible.builtin.stat:
path: /etc/foo.conf
register: st
- name: Fail if the file does not belong to 'root'
ansible.builtin.fail:
msg: "Whoops! file ownership has changed"
when: st.stat.pw_name != 'root'
# Determine if a path exists and is a symlink. Note that if the path does
# not exist, and we test sym.stat.islnk, it will fail with an error. So
# therefore, we must test whether it is defined.
# Run this to understand the structure, the skipped ones do not pass the
# check performed by 'when'
- name: Get stats of the FS object
ansible.builtin.stat:
path: /path/to/something
register: sym
- name: Print a debug message
ansible.builtin.debug:
msg: "islnk isn't defined (path doesn't exist)"
when: sym.stat.islnk is not defined
- name: Print a debug message
ansible.builtin.debug:
msg: "islnk is defined (path must exist)"
when: sym.stat.islnk is defined
- name: Print a debug message
ansible.builtin.debug:
msg: "Path exists and is a symlink"
when: sym.stat.islnk is defined and sym.stat.islnk
- name: Print a debug message
ansible.builtin.debug:
msg: "Path exists and isn't a symlink"
when: sym.stat.islnk is defined and sym.stat.islnk == False
# Determine if a path exists and is a directory. Note that we need to test
# both that p.stat.isdir actually exists, and also that it's set to true.
- name: Get stats of the FS object
ansible.builtin.stat:
path: /path/to/something
register: p
- name: Print a debug message
ansible.builtin.debug:
msg: "Path exists and is a directory"
when: p.stat.isdir is defined and p.stat.isdir
- name: Don not do checksum
ansible.builtin.stat:
path: /path/to/myhugefile
get_checksum: no
- name: Use sha256 to calculate checksum
ansible.builtin.stat:
path: /path/to/something
checksum_algorithm: sha256
get_url
- name: Download foo.conf
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
mode: '0440'
- name: Download file and force basic auth
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
force_basic_auth: yes
- name: Download file with custom HTTP headers
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
headers:
key1: one
key2: two
- name: Download file with check (sha256)
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
checksum: sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
- name: Download file with check (md5)
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
checksum: md5:66dffb5228a211e61d6d7ef4a86f5758
- name: Download file with checksum url (sha256)
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
checksum: sha256:http://example.com/path/sha256sum.txt
- name: Download file from a file path
get_url:
url: file:///tmp/afile.txt
dest: /tmp/afilecopy.txt
- name: < Fetch file that requires authentication.
username/password only available since 2.8, in older versions you need to use url_username/url_password
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
username: bar
password: '{{ mysecret }}'
fail
- name: Example using fail and when together
fail:
msg: The system may not be provisioned according to the CMDB status.
when: cmdb_status != "to-be-staged"
debug
- name: Print the gateway for each host when defined
ansible.builtin.debug:
msg: System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}
when: ansible_default_ipv4.gateway is defined
- name: Get uptime information
ansible.builtin.shell: /usr/bin/uptime
register: result
- name: Print return information from the previous task
ansible.builtin.debug:
var: result
verbosity: 2
- name: Display all variables/facts known for a host
ansible.builtin.debug:
var: hostvars[inventory_hostname]
verbosity: 4
- name: Prints two lines of messages, but only if there is an environment value set
ansible.builtin.debug:
msg:
- "Provisioning based on YOUR_KEY which is: {{ lookup('env', 'YOUR_KEY') }}"
- "These servers were built using the password of '{{ password_used }}'. Please retain this for later use."
ping
检查指定节点机器是否还能连通,用法很简单,不涉及参数. 主机如果在线,则回复pong. 测试连通性的模块.
- ping
Value provided with the data parameter.
returned: success
sample: pong
type: str
cron
- name: Ensure a job that runs at 2 and 5 exists. Creates an entry like "0 5,2 * * ls -alh > /dev/null"
ansible.builtin.cron:
name: "check dirs"
minute: "0"
hour: "5,2"
job: "ls -alh > /dev/null"
- name: 'Ensure an old job is no longer present. Removes any job that is prefixed by "#Ansible: an old job" from the crontab'
ansible.builtin.cron:
name: "an old job"
state: absent
- name: Creates an entry like "@reboot /some/job.sh"
ansible.builtin.cron:
name: "a job for reboot"
special_time: reboot
job: "/some/job.sh"
- name: Creates an entry like "PATH=/opt/bin" on top of crontab
ansible.builtin.cron:
name: PATH
env: yes
job: /opt/bin
- name: Creates an entry like "APP_HOME=/srv/app" and insert it after PATH declaration
ansible.builtin.cron:
name: APP_HOME
env: yes
job: /srv/app
insertafter: PATH
- name: Creates a cron file under /etc/cron.d
ansible.builtin.cron:
name: yum autoupdate
weekday: "2"
minute: "0"
hour: "12"
user: root
job: "YUMINTERACTIVE=0 /usr/sbin/yum-autoupdate"
cron_file: ansible_yum-autoupdate
- name: Removes a cron file from under /etc/cron.d
ansible.builtin.cron:
name: "yum autoupdate"
cron_file: ansible_yum-autoupdate
state: absent
- name: Removes "APP_HOME" environment variable from crontab
ansible.builtin.cron:
name: APP_HOME
env: yes
state: absent
find
帮助在被管理的受控主机中查找符合条件的文件,就像 find 命令一样.
常用选项:
paths: 必须参数,指定在哪个目录中查找文件,可以指定多个路径,路径间用逗号隔开,此参数有别名,使用别名 path 或者别名 name 可以代替 paths。
recurse: 默认情况下,只会在指定的目录中查找文件,也就是说,如果目录中还包含目录,ansible 并不会递归的进入子目录查找对应文件,如果想要递归的查找文件,需要使用 recurse 参数,当 recurse 参数设置为 yes 时,表示在指定目录中递归的查找文件。
hidden: 默认情况下,隐藏文件会被忽略,当 hidden 参数的值设置为 yes 时,才会查找隐藏文件。
file_type: 默认情况下,ansible 只会根据条件查找”文件”,并不会查找”目录”或”软链接”等文件类型,如果想要指定查找的文件类型,可以通过 file_type 指定文件类型,可指定的文件类型有 any、directory、file、link 四种。
patterns: 使用此参数指定需要查找的文件名称,支持使用 shell(比如通配符)或者正则表达式去匹配文件名称,默认情况下,使用 shell 匹配对应的文件名,如果想要使用 python 的正则去匹配文件名,需要将 use_regex 参数的值设置为 yes。
**use_regex:**默认情况下,find 模块不会使用正则表达式去解析 patterns 参数中对应的内容,当 use_regex 设置为 yes 时,表示使用 python 正则解析 patterns 参数中的表达式,否则,使用 glob 通配符解析 patterns 参数中的表达式。
**contains:**使用此参数可以根据文章内容查找文件,此参数的值为一个正则表达式,find 模块会根据对应的正则表达式匹配文件内容。
age: 使用此参数可以根据时间范围查找文件,默认以文件的 mtime 为准与指定的时间进行对比,比如,如果想要查找 mtime 在3天之前的文件,那么可以设置 age=3d,如果想要查找 mtime 在3天以内的文件,可以设置 age=-3d,这里所说的3天是按照当前时间往前推3天,可以使用的单位有秒(s)、分(m)、时(h)、天(d)、星期(w)。
age_stamp: 文件的时间属性中有三个时间种类,atime、ctime、mtime,当我们根据时间范围查找文件时,可以指定以哪个时间种类为准,当根据时间查找文件时,默认以 mtime 为准。
size: 使用此参数可以根据文件大小查找文件,比如,如果想要查找大于3M的文件,那么可以设置 size=3m,如果想要查找小于50k的文件,可以设置 size=-50k,可以使用的单位有 t、g、m、k、b。
get_checksum: 当有符合查找条件的文件被找到时,会同时返回对应文件的 sha1校验码,如果要查找的文件比较大,那么生成校验码的时间会比较长
- name: Recursively find /tmp files older than 2 days
find:
paths: /tmp
age: 2d
recurse: yes
- name: Recursively find /tmp files older than 4 weeks and equal or greater than 1 megabyte
find:
paths: /tmp
age: 4w
size: 1m
recurse: yes
- name: Recursively find /var/tmp files with last access time greater than 3600 seconds
find:
paths: /var/tmp
age: 3600
age_stamp: atime
recurse: yes
- name: Find /var/log files equal or greater than 10 megabytes ending with .old or .log.gz
find:
paths: /var/log
patterns: '*.old,*.log.gz'
size: 10m
# Note that YAML double quotes require escaping backslashes but yaml single quotes do not.
- name: Find /var/log files equal or greater than 10 megabytes ending with .old or .log.gz via regex
find:
paths: /var/log
patterns: "^.*?\\.(?:old|log\\.gz)$"
size: 10m
use_regex: yes
- name: Find /var/log all directories, exclude nginx and mysql
find:
paths: /var/log
recurse: no
file_type: directory
excludes: 'nginx,mysql'
# When using patterns that contain a comma, make sure they are formatted as lists to avoid splitting the pattern
- name: Use a single pattern that contains a comma formatted as a list
find:
paths: /var/log
file_type: file
use_regex: yes
patterns: ['^_[0-9]{2,4}_.*.log$']
- name: Use multiple patterns that contain a comma formatted as a YAML list
find:
paths: /var/log
file_type: file
use_regex: yes
patterns:
- '^_[0-9]{2,4}_.*.log$'
- '^[a-z]{1,5}_.*log$'
RETURN VALUES:
- examined
Number of filesystem objects looked at
returned: success
sample: 34
type: int
- files
All matches found with the specified criteria (see stat module for full output of each dictionary)
returned: success
sample:
- '...': '...'
checksum: 16fac7be61a6e4591a33ef4b729c5c3302307523
mode: '0644'
path: /var/tmp/test1
- '...': '...'
path: /var/tmp/test2
type: list
- matched
Number of matches
returned: success
sample: 14
type: int
- skipped_paths
skipped paths and reasons they were skipped
returned: success
sample:
/laskdfj: '''/laskdfj'' is not a directory'
type: dict
added in: version 2.12 of ansible-core
setup
用于收集远程受控主机的一些基本信息.
**filter参数:**用于进行条件过滤。如果设置,仅返回匹配过滤条件的信息
# Display facts from all hosts and store them indexed by I(hostname) at C(/tmp/facts).
# ansible all -m ansible.builtin.setup --tree /tmp/facts
# Display only facts regarding memory found by ansible on all hosts and output them.
# ansible all -m ansible.builtin.setup -a 'filter=ansible_*_mb'
# Display only facts returned by facter.
# ansible all -m ansible.builtin.setup -a 'filter=facter_*'
# Collect only facts returned by facter.
# ansible all -m ansible.builtin.setup -a 'gather_subset=!all,!any,facter'
- name: Collect only facts returned by facter
ansible.builtin.setup:
gather_subset:
- '!all'
- '!any'
- facter
- name: Collect only selected facts
ansible.builtin.setup:
filter:
- 'ansible_distribution'
- 'ansible_machine_id'
- 'ansible_*_mb'
# Display only facts about certain interfaces.
# ansible all -m ansible.builtin.setup -a 'filter=ansible_eth[0-2]'
# Restrict additional gathered facts to network and virtual (includes default minimum facts)
# ansible all -m ansible.builtin.setup -a 'gather_subset=network,virtual'
# Collect only network and virtual (excludes default minimum facts)
# ansible all -m ansible.builtin.setup -a 'gather_subset=!all,!any,network,virtual'
# Do not call puppet facter or ohai even if present.
# ansible all -m ansible.builtin.setup -a 'gather_subset=!facter,!ohai'
# Only collect the default minimum amount of facts:
# ansible all -m ansible.builtin.setup -a 'gather_subset=!all'
# Collect no facts, even the default minimum subset of facts:
# ansible all -m ansible.builtin.setup -a 'gather_subset=!all,!min'
# Display facts from Windows hosts with custom facts stored in C(C:\custom_facts).
# ansible windows -m ansible.builtin.setup -a "fact_path='c:\custom_facts'"
# Gathers facts for the machines in the dbservers group (a.k.a Delegating facts)
- hosts: app_servers
tasks:
- name: Gather facts from db servers
ansible.builtin.setup:
delegate_to: "{{ item }}"
delegate_facts: true
loop: "{{ groups['dbservers'] }}"




