文章目录
一、ad-hoc介绍
“Ad-hoc"这个词组的全称就是"ad hoc”,它本身就是一个完整的拉丁语短语,意思是“为了这个目的”或“特别为此”。在英语中,它通常用来描述临时的、特别的或即兴的解决方案或决策。在技术领域,尤其是在Ansible这样的自动化工具中,"ad-hoc"命令指的是那些不需要预先编写完整剧本(playbook)就能执行的一次性任务。因此,"ad-hoc"并没有一个更长的全称,它本身就是一个完整的术语。
“Ad-hoc"这个词组的全称就是"ad
hoc”,它本身就是一个完整的拉丁语短语,意思是“为了这个目的”或“特别为此”。在英语中,它通常用来描述临时的、特别的或即兴的解决方案或决策。在技术领域,尤其是在Ansible这样的自动化工具中,"ad-hoc"命令指的是那些不需要预先编写完整剧本(playbook)就能执行的一次性任务。因此,"ad-hoc"并没有一个更长的全称,它本身就是一个完整的术语。
"ad-hoc"这个词的发音是 [ˌæd ˈhɒk](英式发音)或 [ˌæd ˈhɑːk](美式发音)。其中 “ad” 读作
“æd”,“hoc” 读作 “hɒk”(英式)或 “hɑːk”(美式)。这个词组通常作为一个整体来读,不分开。 Ansible 的
ad-hoc 命令是一个强大的功能,允许你在没有编写 Ansible playbook
的情况下,直接在目标主机上执行命令。它提供了一种快速且灵活的方式来执行各种任务,比如配置更改、系统检查和软件安装。
Ansible 的 ad-hoc 命令是一种即时执行单次任务的方式,无需创建和维护 playbook。它通过命令行直接指定要执行的模块和参数,并将这些指令应用于目标主机或主机组。
如何使用 Ansible Ad-Hoc 命令
1. 基本语法
ansible <主机组> -m <模块> -a "<模块参数>"
<主机组>
: 目标主机或主机组的名称,在 Ansible 的 inventory 文件中定义。<模块>
: 要使用的 Ansible 模块,比如ping
、command
、shell
、yum
等。<模块参数>
: 传递给模块的参数,通常是以键值对的形式。
2. 示例
-
测试主机连通性
ansible all -m ping
这个命令会使用
ping
模块来测试所有主机的连通性。如果主机正常响应,它会返回pong
。 -
执行远程命令
ansible webservers -m shell -a "uptime"
这个命令会在所有
webservers
主机组中的主机上执行uptime
命令,显示系统的运行时间和负载信息。 -
安装软件包
ansible dbservers -m yum -a "name=httpd state=present"
这个命令会在
dbservers
主机组中的所有主机上使用yum
模块安装httpd
软件包。 -
复制文件
ansible all -m copy -a "src=/local/path/to/file dest=/remote/path/to/file"
这个命令会将本地路径
/local/path/to/file
复制到远程主机的路径/remote/path/to/file
。
应用场景
-
快速测试和调试: Ad-hoc 命令非常适合用来快速测试某些功能或调试问题,而不需要编写完整的 playbook。
-
一次性操作: 对于一些一次性的配置更改或操作,比如安装一个软件包或重启服务,ad-hoc 命令是一个高效的选择。
-
批量管理: 使用 ad-hoc 命令可以同时对多个主机执行相同的操作,比如更新系统或执行安全检查。
注意事项
- 权限: 确保你有权限在目标主机上执行所需的操作,有些操作可能需要 root 权限。
- 安全: 使用 ad-hoc 命令时要小心,以避免对生产环境造成不必要的影响。
- 性能: 对于大规模的操作或复杂的任务,建议使用 playbook,以便更好地管理和维护配置。
通过 ad-hoc 命令,你可以快速、灵活地管理和配置你的服务器,帮助你在日常工作中提高效率。
二、Ansible模块
Ansible 是一个开源的自动化工具,用于配置管理、应用程序部署和任务自动化。Ansible 的模块是执行任务的基本单元,每个模块都是一个 Python 脚本或插件,用于与目标系统交互。模块的通用组成包括以下几个部分:
-
模块的入口点:
- 模块通常由一个名为
main
的函数或类的实例化来定义,这是模块的执行入口。
- 模块通常由一个名为
-
参数定义:
- 模块接收参数,这些参数通过 Ansible 的任务定义传递。参数可以在模块的
argument_spec
中定义。它们描述了模块可以接受的选项、数据类型、是否必需等。
- 模块接收参数,这些参数通过 Ansible 的任务定义传递。参数可以在模块的
-
逻辑处理:
- 模块包含实现特定功能的核心逻辑。例如,创建文件、安装软件包、修改配置等。这部分的代码处理传递给模块的参数,执行必要的操作,并产生相应的结果。
-
返回结果:
- 模块需要以特定格式返回结果,通常是 JSON 格式。结果包含任务的成功状态、返回的消息、可能的变更等信息。Ansible 根据这些信息来报告任务的状态给用户。
-
错误处理:
- 模块应具备处理和报告错误的能力。如果模块在执行过程中遇到问题,它应能以清晰的方式报告错误,并返回相应的错误信息。
-
文档字符串:
- 模块通常包含一个文档字符串,描述模块的功能、参数及用法。这有助于用户理解如何使用该模块。
-
依赖管理:
- 某些模块可能需要依赖其他 Python 库或系统工具。在模块中,可以通过导入相关库或检查系统环境来管理这些依赖。
-
测试和调试:
- 模块应包含测试和调试功能,以确保其在不同环境下的正确性和可靠性。这可以包括内置测试用例或调试输出。
以下是一个简单的 Ansible 模块示例(用 Python 编写):
#!/usr/bin/python
from ansible.module_utils.basic import AnsibleModule
def run_module():
module_args = dict(
name=dict(type='str', required=True),
state=dict(type='str', required=True, choices=['present', 'absent'])
)
result = dict(
changed=False,
original_message='',
message=''
)
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
name = module.params['name']
state = module.params['state']
# Implement module logic here
if state == 'present':
result['changed'] = True
result['message'] = 'Item {} is present'.format(name)
elif state == 'absent':
result['changed'] = True
result['message'] = 'Item {} is absent'.format(name)
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()
这个示例模块接受两个参数 name
和 state
,然后根据 state
的值生成响应的消息。根据具体实现的复杂性,模块的组成和功能可能会有所不同,但这些基本组成部分是大多数 Ansible 模块所共有的。
Ansible的模块列举(不全)
具体在官网上查找
Ansible 的模块非常丰富,以下是一些常用的模块分类:
系统模块
- command:执行命令
- shell:在 shell 中执行命令
- copy:复制文件
- file:管理文件和目录属性
- user:管理用户账户
网络模块
- ping:测试连接
- uri:与网络资源进行交互
- net_ping:测试网络连通性
云模块
- ec2:管理 AWS EC2 实例
- gce:管理 Google Cloud 实例
- azure_rm:管理 Azure 资源
数据库模块
- mysql_db:管理 MySQL 数据库
- postgresql_db:管理 PostgreSQL 数据库
git、template、assemble
- git:管理 Git 仓库
- template:处理 Jinja2 模板
- assemble:合并文件
Web 服务器模块
- apache2_module:管理 Apache 模块
- nginx:管理 Nginx 配置
软件包管理模块
- apt:管理 Debian/Ubuntu 软件包
- yum:管理 RHEL/CentOS 软件包
- pip:管理 Python 包
文件模块
- fetch:从远程主机获取文件
- template:使用模板生成配置文件
- unarchive:解压归档文件
安全模块
- firewalld:管理 Linux 防火墙
- seboolean:管理 SELinux 布尔值
系统监控模块
- cron:管理定时任务
- service:管理系统服务
版本控制模块
- git:克隆、拉取和管理 Git 仓库
存储模块
- mount:管理文件系统挂载
- parted:管理磁盘分区
变量和模板模块
- set_fact:设置和更新变量
- include_tasks:包含其他任务文件
调试模块
- debug:输出调试信息
- pause:暂停执行
监控和日志模块
- logrotate:管理日志轮换
- syslog:配置系统日志
备份和恢复模块
- copy:复制文件进行备份
- synchronize:使用 rsync 进行数据同步
用户和权限模块
- group:管理用户组
- sudoers:管理 sudo 权限
任务和流程控制模块
- block:将多个任务组合在一起
- wait_for:等待某个条件满足(如端口开放)
uri、get_url
- uri:与 REST API 进行交互
- get_url:从 URL 下载文件
监控和管理模块
- setup:收集目标主机的系统信息
- ansible.builtin.facts:获取主机的事实信息
服务和进程模块
- systemd:管理 systemd 服务
- service:管理系统服务(SysV init)
网络配置模块
- network_connections:管理网络连接
- ios_config:管理 Cisco IOS 设备配置
证书管理模块
- acme_certificate:管理 ACME 证书
- openssl_certificate:创建和管理 OpenSSL 证书
多平台支持模块
- win_feature:管理 Windows 功能
- win_service:管理 Windows 服务
任务重试模块
- wait_for_connection:等待连接可用
- retry:重试任务
配置管理模块
- template:处理 Jinja2 模板生成配置
- ini_file:管理 INI 配置文件
测试和验证模块
- assert:进行断言检查
- wait_for:等待特定条件满足
部署模块
- git:从 Git 仓库检出代码
- unarchive:解压归档文件
高级功能模块
- delegate_to:将任务委托给其他主机
- import_playbook:导入其他 Playbook
Ansible模块的参数与其搭配的指令
Ansible 的模块可以用于自动化系统配置和管理,模块通常有一些通用的参数,虽然具体的参数取决于模块的类型和功能。以下是一些常用的 Ansible 模块的通用参数及其说明:
1. name
:
- 描述: 指定资源的名称或目标。
- 示例: 在
package
模块中,name
用于指定要安装或删除的软件包的名称。
2. state
:
- 描述: 定义资源的目标状态。
- 选项:
present
或installed
:资源应存在(如安装包、文件等)。absent
或removed
:资源应不存在。started
:服务应启动。stopped
:服务应停止。restarted
:服务应重新启动。latest
:例如软件包应更新到最新版本。
- 示例: 在
service
模块中,state
可以设置为started
或stopped
。
3. src
:
- 描述: 指定源文件或目录路径。
- 示例: 在
copy
模块中,src
用于指定本地文件路径,准备复制到目标主机。
4. dest
:
- 描述: 指定目标路径。
- 示例: 在
copy
模块中,dest
用于指定文件应该复制到的路径。
5. user
:
- 描述: 指定执行操作的用户。
- 示例: 在
file
模块中,user
用于设置文件或目录的所有者。
6. group
:
- 描述: 指定文件或目录所属的组。
- 示例: 在
file
模块中,group
用于设置文件或目录的组。
7. mode
:
- 描述: 设置文件或目录的权限模式。
- 示例: 在
file
模块中,mode
用于设置权限,例如0755
。
为什么是“0755”而不是“755” :
在这种情况下,mode
参数通常用于指定文件的访问权限。数字0755
是一个八进制数,用于Unix和类Unix系统中设置文件权限。这里的0755
表示:
0
:表示这是一个八进制数。7
:代表文件所有者(owner)具有读(4)、写(2)和执行(1)权限,总和为7。- 第二个
5
:代表与文件所有者同组的用户(group)具有读(4)和执行(1)权限,总和为5。 - 第三个
5
:代表其他用户(others)也具有读(4)和执行(1)权限,总和为5。
因此,0755
意味着文件所有者可以完全控制文件,而同组用户和其他用户可以读取和执行文件,但不能写入。
在Unix和类Unix系统中,权限数字通常以八进制形式表示,所以0755
中的前导0
是必要的,它告诉系统这是一个八进制数。如果你只写755
,系统会将其解释为十进制数,这将导致不同的权限设置。
十进制数755
转换为八进制是0b111 101 101
,这在八进制中表示为0755
。但是,如果你在设置权限时使用755
而不是0755
,系统会将其解释为十进制数755
,这在八进制中实际上是0b544
,这会导致不同的权限设置,通常不是你想要的。
因此,为了确保权限正确设置为所有者全部权限,组和其他用户读/执行权限,你应该使用0755
。
在编程中,特别是在Python语言中,0b
是一个二进制数的前缀。当你在数字前面加上0b
,它告诉解释器这个数字是一个二进制数。例如,0b1011
是一个二进制数,它等价于十进制数11
。
然而,在你提到的上下文中,0755
是一个八进制数,不是二进制数。在Unix和类Unix系统中,文件权限通常以八进制数的形式表示。八进制数的前缀是0
,而不是0b
。所以,0755
是一个八进制数,它表示文件的权限设置。
总结一下:
0b
前缀用于表示二进制数。0
前缀用于表示八进制数。- 没有前缀的数字默认是十进制数。
8. delegate_to
:
- 描述: 指定将任务委托到其他主机执行。
- 示例: 用于在 Ansible Playbook 中将特定任务委托到不同的主机。
9. args
:
- 描述: 用于传递其他参数,模块通常会接受以字典形式提供的额外参数。
- 示例: 在一些模块中,如
command
,args
可以用于指定额外的命令行参数。
10. 指令with_items
:
- 描述: 用于循环处理列表中的每一项。
- 示例: 在
yum
模块中,可以使用with_items
来逐个安装列表中的软件包。
11. 指令register
:
- 描述: 将任务的结果存储在变量中,以便后续使用。
- 示例: 在 Playbook 中,可以用
register
将任务结果保存为变量以便进一步操作。
在Ansible中,
register
关键字用于将任务的输出结果保存到一个变量中,以便在剧本(playbook)的其他部分进行引用。这个变量通常被称为“fact变量”或“注册变量”。以下是register
关键字的具体使用方法:
-----基本语法
- name: Task name
shell: your_command
register: variable_name
name
:任务的名称,用于日志记录和调试。shell
:要执行的命令。你也可以使用其他模块,如command
、copy
、file
等。register
:将任务的输出保存到变量中,变量名由你指定。
-----使用注册变量
一旦你使用
register
关键字注册了一个变量,你就可以在后续的任务中使用这个变量。注册变量通常包含几个属性,如stdout
、stderr
、changed
、failed
等。
stdout
:命令的标准输出。stderr
:命令的标准错误输出。changed
:如果任务改变了系统状态(例如,文件被创建或修改),这个值会是True
。failed
:如果任务执行失败,这个值会是True
。在 Ansible 中,注册变量的基本结构是使用
register
关键字。注册的变量本身是一个字典,包含多个子元素,通常包括:
changed
:布尔值,指示任务是否更改了系统状态。
failed
:布尔值,指示任务是否失败。
invocation
:包含任务的调用信息,包括参数和任务名称。
msg
:任务输出的消息,通常是来自命令或模块的标准输出。
rc
:返回码,通常用于表示命令执行的状态,0 表示成功。
stdout
:标准输出,包含命令执行时的输出内容。
stderr
:标准错误,包含命令执行时的错误信息。这些子元素可以帮助你详细了解任务的执行结果,并在后续的任务中进行逻辑判断和条件控制。使用注册变量时,通常会以
register: var_name
的方式创建变量,例如:
- command: /path/to/command
register: command_output
然后你可以通过
command_output.changed
、command_output.stdout
等方式访问相应的子元素。
stdout_lines
:将标准输出按行拆分的列表,便于逐行处理。
stderr_lines
:将标准错误按行拆分的列表。
results
:在使用某些模块时,如with_items
,包含所有循环项的结果。
item
:在循环任务中,当前处理的项。
warnings
:任何与任务相关的警告信息。这些子元素能够提供更详细的任务执行信息,帮助你在剧本中进行调试和条件判断。
示例
- name: Get the current date
shell: date
register: current_date
- name: Print the current date
debug:
msg: "The current date is {{ current_date.stdout }}"
在这个例子中,
date
命令的输出被保存在current_date
变量中。然后,你可以在debug
模块中使用current_date.stdout
来访问和打印这个输出。
-----高级用法
注册变量也可以用于条件判断和循环:
- name: Check if file exists
stat:
path: /path/to/file
register: file_info
- name: Do something if file exists
shell: echo "File exists"
when: file_info.stat.exists
在这个例子中,
stat
模块用于获取文件的状态,并将结果保存在file_info
变量中。然后,使用when
条件来判断文件是否存在,并根据结果执行相应的任务。-----注意事项
- 注册变量的名称应该是唯一的,以避免覆盖。
- 使用注册变量时,应该根据需要选择合适的属性,例如
stdout
、stderr
等。- 注册变量在任务执行后立即可用,但它们的作用域通常仅限于当前剧本。
通过使用
register
关键字,你可以在Ansible剧本中灵活地处理和重用任务的输出。
12. 指令when
:
- 描述: 根据条件判断是否执行任务。
- 示例: 在 Playbook 中使用
when
来控制任务的执行条件。
这些参数通常可以与具体的 Ansible 模块结合使用,以实现复杂的自动化任务。模块的文档会提供详细的参数说明和示例,可以查阅 Ansible 官方文档 来获取更多具体的模块信息。
Ansible 是一个强大的自动化工具,它使用模块来执行各种任务。每个模块都有自己特定的参数,但有一些通用的参数可以在多个模块中使用。以下是
Ansible 模块常见的通用参数及其说明:
become
:
- 说明:用于提升权限。设置为
yes
时,模块会使用提权工具(如sudo
)来执行任务。- 示例:
become: yes
become_user
:
- 说明:指定提权后的用户身份。
become
参数为yes
时,这个参数会指定使用哪个用户来执行任务。- 示例:
become_user: www-data
become_method
:
- 说明:指定提权的方法。常用的值包括
sudo
,su
,pbrun
,pfexec
,doas
等。- 示例:
become_method: sudo
delegate_to
:
- 说明:指定将任务委派给其他主机来执行,而不是当前主机。
- 示例:
delegate_to: dbserver.example.com
ignore_errors
:
- 说明:设置为
yes
时,即使任务失败也会继续执行其他任务。用于容忍某些任务失败。- 示例:
ignore_errors: yes
register
:
- 说明:将任务的输出结果保存到变量中,以便后续任务使用。
- 示例:
register: result
until
:
- 说明:指定一个条件,任务将反复执行直到条件成立或者达到最大重试次数。
- 示例:
until: result.rc == 0
retries
:
- 说明:与
until
配合使用,指定任务最大重试次数。- 示例:
retries: 5
delay
:
- 说明:与
until
和retries
配合使用,指定每次重试之间的等待时间(以秒为单位)。- 示例:
delay: 10
timeout
:
- 说明:设置任务的超时时间(以秒为单位),超出时间后任务将被中断。
- 示例:
timeout: 60
这些通用参数帮助你在编写 Ansible
剧本时更好地控制任务的执行方式和处理结果。具体模块可能会有自己的专用参数,但了解这些通用参数可以让你更加灵活地管理和优化自动化任务。
shell模块
ansible web_group -m shell -a 'df -h'
ansible web_group -m shell -a 'ps -ef | grep nginx'
Ansible 中的 shell
模块可以用来执行任意的 shell 命令,以下是具体用法和示例:
基本语法:
- name: Execute a shell command
shell: <command>
或
ansible -m shell -a '命令内容'
示例:
执行简单命令:
- name: Print Hello, World!
shell: echo "Hello, World!"
使用管道和重定向:
- name: List files and save output to a file
shell: ls -l /some/directory > output.txt
使用变量:
- name: Create a directory
shell: mkdir -p /tmp/{{ directory_name }}
vars:
directory_name: mydir
获取命令输出:
- name: Get the current date
shell: date
register: current_date
- name: Print the current date
debug:
msg: "The current date is {{ current_date.stdout }}"
注意事项:
- 使用
shell
时需小心注入攻击,确保命令安全。 - 对于简单命令,优先使用
command
模块,因为它更安全。
测试:
---
- name: the playbook to test shell module
hosts: localhost
become: no
tasks:
- name: the task to test the register-step1
# shell:
# name: 'date'
shell: date
register: current_date
- name: the task to test the register-step2
debug:
msg: 'the current_date value is {{current_date.stdout}}'
使用command模块比shell模块更安全?
Ansible 的 command
模块比 shell
模块更安全,主要是因为:
- 不使用 shell:
command
模块直接调用指定的命令,不通过 shell 解析,这样可以避免 shell 注入攻击的风险。 - 简化命令执行:
command
模块仅执行单个命令,不支持 shell 的管道和重定向,减少了潜在的复杂性和安全漏洞。
shell
模块和 command
模块在 Ansible 中有几个关键的区别:
一、 1. 执行方式
- command 模块:
- 直接执行指定的命令,不经过 shell。
- 不能使用 shell 特性(如管道
|
、重定向>
、变量替换等)。
- name: Use command module
command: /path/to/your/command arg1 arg2
- shell 模块:
- 通过 shell 执行命令,允许使用 shell 特性。
- 可以执行更复杂的命令,例如使用管道、重定向和其他 shell 功能。
- name: Use shell module
shell: echo "Hello World" | grep "Hello"
二、 2. 安全性
command 模块:
- 更安全,因为不涉及 shell,因此没有 shell 注入的风险。
shell 模块:
- 较不安全,使用 shell 时可能引入注入攻击风险,尤其是处理用户输入时。
在处理用户输入时,引入 shell 攻击风险的原因主要有以下几点:
用户输入未经验证:如果直接将用户输入作为命令的一部分执行,攻击者可以通过精心构造的输入插入恶意命令。
特殊字符的处理:Shell 允许使用许多特殊字符(如
;
,&
,|
,>
等),攻击者可以利用这些字符执行额外的命令或进行重定向。命令组合:攻击者可以通过输入多个命令,使得一个原本安全的命令变得危险,例如使用分号
;
来分隔多个命令。环境变量:攻击者可以利用环境变量来影响命令的执行,特别是在脚本中。
为了防止这种风险,在处理用户输入时,应该严格验证和清理输入,尽量使用不依赖于 shell 的执行方式,例如 Ansible 的
command
模块。这样可以有效降低注入攻击的可能性。
三、 3. 返回值
- 两者都返回相似的信息(如标准输出、标准错误和返回码),但
shell
模块可能更复杂,特别是当命令包含多个步骤时。四、 4. 适用场景
command 模块:
- 适合执行简单命令,且不需要 shell 功能的情况。
shell 模块:
- 适合需要使用 shell 特性的场景,如脚本执行、使用管道和重定向等。
总的来说,优先使用
command
模块来确保安全性,只有在确实需要使用 shell 特性时才使用shell
模块。这样可以减少潜在的安全风险。
command模块
不能全部识别shell中的特殊符号,如:command无法使用管道符“|”
验证:
ansible web_group -m command -a 'ps -ef | grep nginx'
Ansible 的 command
模块用于在目标主机上执行命令。它的主要特点是不会通过 shell 运行命令,因此不支持管道、重定向等 shell 特性。以下是 command
模块的详细使用方法及所有可用参数:
一、 基本语法
- name: Description of the task
command: <command> [args]
二、 可用参数
_raw_params
:- 用于传递原始命令和参数。
- 不需要指定命令名称。
可以简化参数输入:
-
chdir
:- 指定命令的工作目录。
- 允许命令在指定目录下运行。
表示在执行命令之前,先切换到指定目录中去
- name: Run a script in a specific directory command: ./script.sh args: chdir: /path/to/directory
-
改变命令的执行环境:通过指定chdir参数,你可以确保命令在特定的目录下执行。这对于需要访问特定路径下的文件或目录的命令来说非常重要。
-
简化命令:如果命令依赖于相对于当前目录的路径,使用chdir可以避免在命令中使用绝对路径或相对路径。这样可以使命令更简洁、更易于理解和维护。
-
避免路径冲突:在某些情况下,如果你在多个目录中有同名的文件或脚本,使用chdir可以明确指定命令应该在哪个目录下执行,从而避免路径冲突。
-
提高安全性:通过限制命令的执行目录,可以减少命令访问不相关文件或目录的风险,从而提高安全性。
-
便于自动化和脚本编写:在自动化任务或编写脚本时,chdir可以确保命令在预期的环境中执行,这对于确保脚本的可靠性和可重复性非常重要。
测试:
---
- name: the play1
hosts: localhost
become: no
tasks:
- name: the task1
command: "touch test_command_chdir.txt"
args:
chdir: /opt/
不加chdir
参数,那么会默认在家目录执行命令:
---
- name: the play1
hosts: localhost
become: no
tasks:
- name: the task1
command: "touch test_command_chdir2.txt"
-
creates
:- 如果指定的文件存在,则跳过该任务,减少资源的使用,或避免默认替换原文件内容。
- 适用于创建文件或目录的命令。
- name: Create a file if it doesn't exist command: touch /tmp/myfile args: creates: /tmp/myfile
因为使用touch创建文件时,如果有同名文件,那么会默认替换
-
removes
:- 如果指定的文件不存在,则跳过该任务。
- 通常用于删除文件。
- name: Remove a file if it exists command: rm /tmp/myfile args: removes: /tmp/myfile
测试:
不加removes参数后:
加removes
参数后:
-
warn
:- 设置是否在命令运行时发出警告。
- 默认值为
yes
,可以设置为no
以禁用警告。
- name: Run a command with no warning command: some_command args: warn: no
测试:
- 不加
warn
参数,会有warning出现:
- 对比之前的,加了
warn
参数后,warning就不出现了
三、示例任务
以下是一个包含多种参数的完整示例:
- hosts: all
tasks:
- name: Create a temporary directory if it doesn't exist
command: mkdir /tmp/mydir
args:
creates: /tmp/mydir
- name: Change to the temporary directory and list files
command: ls
args:
chdir: /tmp/mydir
- name: Run a script if it exists
command: ./myscript.sh
args:
warn: no
- name: Remove a temporary file if it exists
command: rm /tmp/mydir/tempfile
args:
removes: /tmp/mydir/tempfile
四、捕获输出
使用 register
捕获命令的输出,可以在后续任务中使用:
- name: Get current user
command: whoami
register: current_user
- name: Display current user
debug:
var: current_user.stdout
五、错误处理
使用 ignore_errors
参数处理可能失败的命令:
- name: Try to remove a non-existent file
command: rm /nonexistent/file
ignore_errors: yes
六、 注意事项
command
模块不能处理管道、重定向等 shell 特性。如果需要这些功能,请使用shell
模块。- 确保在执行命令时,所需的权限和环境变量已正确设置。
script模块
管理机脚本推送到其他机器中
ansible web_group -m script -a '/root/test_script_module.sh'
Ansible 的 script
模块用于在远程主机上执行本地脚本。这使得你可以通过 Ansible 直接管理和执行现有的脚本,而无需将其内容手动复制到目标机器。
基本语法
- name: Execute a script on remote hosts
script: /path/to/local/script.sh
参数
script
: 指定要在远程主机上执行的本地脚本的路径。这个路径是相对于运行 Ansible 命令的控制节点的路径。
-
基本示例:
假设你有一个名为hello.sh
的脚本,内容如下:#!/bin/bash echo "Hello, World!"
你可以使用以下 Ansible 剧本来执行这个脚本:
--- - hosts: all tasks: - name: Run hello script script: /path/to/hello.sh
-
传递参数:
如果你的脚本需要接受参数,你可以通过修改脚本,使其能够从环境变量中获取。Ansible 会在执行时自动传递一些变量,如ansible_host
和ansible_user
,你可以在脚本内部使用这些变量。 -
处理返回值:
script
模块会返回脚本的标准输出和标准错误到 Ansible 的输出中,因此你可以根据返回值进行后续操作。例如:- hosts: all tasks: - name: Run a script and capture output script: /path/to/script_with_output.sh register: script_result - debug: var: script_result.stdout
-
使用
become
提升权限:
如果脚本需要更高的权限(如 root 权限),你可以结合使用become
参数:- hosts: all tasks: - name: Run script as root script: /path/to/script.sh become: yes
测试:
脚本文件:
#!/bin/bash
echo "Hi! $HOSTNAME"
剧本文件:
---
- name: the play1
hosts: web_servers
become: no
tasks:
- name: the task1
script: test_script_module.sh
environment:
HOSTNAME: "{{ansible_hostname}}"
register: script_result
- name: the task2
debug:
msg: "脚本执行状态为:{{script_result.stdout}}"
注意事项
- 脚本路径:确保指定的脚本路径是正确的,并且脚本具有可执行权限。
- 依赖库:如果你的脚本依赖于特定的库或工具,确保这些依赖已经在目标主机上安装。
- 执行环境:脚本将在目标主机的 Shell 环境中执行,因此任何环境变量或配置都应在脚本中处理。
file模块
如果有同名文件存在,那么会默认替换
参数:
- src=
Path of the file to link to.
This applies only to state=link
and state=hard
.
For state=link
, this will also accept a non-existing path.
Relative paths are relative to the file being created (path
) which
is how the Unix command ln -s SRC DEST
treats relative paths.
[Default: (null)]
type: path
- path=
Path to the file being managed.
(Aliases: dest, name)
type: path
- state=
If absent
, directories will be recursively deleted, and files or
symlinks will be unlinked. In the case of a directory, if diff
is
declared, you will see the files and folders deleted listed under
path_contents
. Note that absent
will not cause file
to fail if
the path
does not exist as the state did not change.
If directory
, all intermediate subdirectories will be created if
they do not exist. Since Ansible 1.7 they will be created with the
supplied permissions.
If file
, without any other options this works mostly as a ‘stat’
and will return the current state of path
. Even with other options
(i.e mode
), the file will be modified but will NOT be created if
it does not exist; see the touch
value or the [copy] or [template]
module if you want that behavior.
If hard
, the hard link will be created or changed.
If link
, the symbolic link will be created or changed.
If touch
(new in 1.4), an empty file will be created if the path
does not exist, while an existing file or directory will receive
updated file access and modification times (similar to the way
touch
works from the command line).
(Choices: absent, directory, file, hard, link, touch)[Default: file]
type: str
- mode=
The permissions the resulting file or directory should have.
For those used to /usr/bin/chmod
remember that modes are actually
octal numbers. You must either add a leading zero so that Ansible’s
YAML parser knows it is an octal number (like 0644
or 01777
) or
quote it (like '644'
or '1777'
) so Ansible receives a string and
can do its own conversion from string into number.
Giving Ansible a number without following one of these rules will
end up with a decimal number which will have unexpected results.
As of Ansible 1.8, the mode may be specified as a symbolic mode (for
example, u+rwx
or u=rw,g=r,o=r
).
[Default: (null)]
type: str
示例:
# 修改文件.....
- name: Change file ownership, group and permissions
file:
path: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
# 修改文件....
- name: Give insecure permissions to an existing file
file:
path: /work
owner: root
group: root
mode: '1777'
#"1777": 这里的"1"表示设置了粘滞位(sticky bit)。粘滞位通常用于公共目录(如/tmp),以限制删除文件的权限。在设置了粘滞位的目录中,用户只能删除或重命名他们拥有的文件,即使他们有权限写入目录。然而,当粘滞位用于文件时(不是目录),它的行为可能会因文件系统的不同而有所差异,并且可能不会提供任何额外的保护。
# 创建链接文件....
- name: Create a symbolic link
file:
src: /file/to/link/to
dest: /path/to/symlink
owner: foo
group: foo
state: link
# 创建链接文件.....
- name: Create two hard links
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)
file:
path: /etc/foo.conf
state: touch
mode: u=rw,g=r,o=r
# 创建普通文件.....
- name: Touch the same file, but add/remove some permissions
file:
path: /etc/foo.conf
state: touch
mode: u+rw,g-wx,o-rwx
- name: Touch again the same file, but dont change times this makes the task idempotent
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
file:
path: /etc/some_directory
state: directory
mode: '0755'
- name: Update modification and access time of given file
file:
path: /etc/some_file
state: file
modification_time: now
access_time: now
- name: Set access time based on seconds from epoch value
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
file:
path: /etc/foo
state: directory
recurse: yes
owner: foo
group: foo
- name: Remove file (delete file)
file:
path: /etc/foo.txt
state: absent
- name: Recursively remove directory
file:
path: /etc/foo
state: absent
测试:
# 修改1.txt的属主、属组以及权限值
- name: task1_test_file_module
file:
path: 1.txt
owner: www
group: www
mode: '0600
# 为1.txt创建软链接,并设置链接的原文件属主、属组(链接文件设置不了指定属主属组)
- name: task2_test_file_module
file:
src: 1.txt
dest: 1.txt_link
owner: www
group: www
state: link
# 创建一个43.txt的文件,并设置属主、属组以及权限值
- name: task3_test_file_module
file:
path: 43.txt
owner: www
group: www
state: touch
mode: '0600'
# 创建一个目录,并设置权限值
- name: task4_test_file_module
file:
path: ./test_file_module
state: directory
mode: '1755'
如何同时创建多个目录?
可以通过使用 with_items
循环来实现。下面是一个示例任务:
- name: Create multiple directories
file:
path: "{{ item }}"
state: directory
loop:
- /path/to/dir1
- /path/to/dir2
- /path/to/dir3
将需要创建的目录路径替换为你自己的路径即可。
循环删除多个目录:
- name: Delete multiple directories
file:
path: "{{item}}"
state: absent
loop:
- /path/to/dir1
- /path/to/dir2
- /path/to/dir3
注:“item"和"with_items"或"loop”
在Ansible playbook中,
item
和with_items
是用于循环遍历列表中的每个元素的关键字。
item
: 这是一个特殊的变量,它在with_items
循环中代表当前迭代的元素。在循环体内部,你可以使用{{ item }}
来引用当前迭代的元素值。
with_items
: 这是一个Ansible的构造,用于创建一个循环,它会遍历后面跟着的列表中的每一个元素。在with_items
后面,你会提供一个列表,Ansible会依次将列表中的每个元素赋值给item
变量,然后执行循环体内的任务。2.X版本后推荐使用**
loop
**来代替"with_items"在你提供的代码片段中:
- name: Create multiple directories
file:
path: "{{ item }}"
state: directory
with_items:
- /path/to/dir1
- /path/to/dir2
- /path/to/dir3
with_items
后面跟着的列表['/path/to/dir1', '/path/to/dir2', '/path/to/dir3']
包含了三个路径字符串。- Ansible 会遍历这个列表,每次迭代都会将列表中的一个路径赋值给
item
变量。- 在每次迭代中,
path: "{{ item }}"
会使用当前的item
值,也就是列表中的一个路径。- 因此,这个任务会被执行三次,每次都会创建一个目录:首先是
/path/to/dir1
,然后是/path/to/dir2
,最后是/path/to/dir3
。这种循环机制使得你可以用一个任务模板来处理多个类似的操作,而不需要为每个操作编写单独的任务。
copy模块
参数
注意:
1、使用copy模块,推送后保持指定属主、属组
2、推送目录时卡住?
如果在使用 Ansible 的
copy
模块时卡住,可以尝试以下解决方法:
使用
rsync
模块:相较于copy
,rsync
更适合大文件或大量文件的传输,能显著提高效率。分批传输:将目录拆分成多个小目录或小文件,逐步传输,避免一次性传输过多。
检查网络连接:确保网络稳定,带宽充足,可以通过
ping
测试连接质量。目标主机性能监控:检查目标主机的 CPU 和内存使用情况,确保其负载不高。
增加 Ansible 任务超时:可以调整 Ansible 的超时设置,防止因超时而失败。
通过这些方法,通常能有效解决任务卡住的问题。
如果在使用 Ansible 的copy
模块时卡住,可以尝试以下解决方法:
使用
rsync
模块:相较于copy
,rsync
更适合大文件或大量文件的传输,能显著提高效率。分批传输:将目录拆分成多个小目录或小文件,逐步传输,避免一次性传输过多。
检查网络连接:确保网络稳定,带宽充足,可以通过
ping
测试连接质量。目标主机性能监控:检查目标主机的 CPU 和内存使用情况,确保其负载不高。
增加 Ansible 任务超时:可以调整 Ansible 的超时设置,防止因超时而失败。
通过这些方法,通常能有效解决任务卡住的问题。
示例
To Do 验证????????
# 文件复制到远程被管理机中
- name: Copy file with owner and permissions
copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
# 复制文件到远程被管理机中,如果远程管理机中的同名文件内容和需要复制的文件不同,那么将备份???
- name: Copy a new "ntp.conf file into place, backing up the original if it differs from the co
copy:
src: /mine/ntp.conf
dest: /etc/ntp.conf
owner: root
group: root
mode: '0644'
backup: yes
# 创建一个单行内容的文件(因为content的类型为str,所有只有单行??)
- name: Copy using inline content
copy:
content: '# This file was moved to /etc/other.conf'
dest: /etc/mine.conf
yum模块
具体使用?:
To 验证???
ansible db01 -m yum -a "name=mariadb-server state=present"
yum-repository模块
具体使用?:
To 验证???
动作选项:
根据仓库文件的内容的选项:
-
name
表示仓库的名字 -
description
对仓库的描述信息 -
baseurl
-
file
-
owner
-
group
-
gpgcheck
- =yes
- =no
-
enabled
- =yes
- =no
-
state=present
创建 -
state=absent
删除
#删除仓库:
ansible web01 -m yum_repository -a 'name=nginx-stable-repos state=absent'
service模块
具体使用?:
To 验证???
动作选项:
-
name
服务名 -
state=
- started
- stopped
- restarted
- reloaded
service模块与systemd模块的区别
service
模块和 systemd
模块在 Ansible 中用于管理服务,但它们之间有一些关键区别:
一、 1. 适用的系统
-
service 模块:
- 适用于传统的 SysVinit 和其他服务管理系统。
- 主要用于管理那些使用
service
命令的系统。
-
systemd 模块:
- 专门为使用 systemd 的系统设计(如现代 Linux 发行版)。
- 提供对 systemd 单元文件的直接支持。
二、 2. 功能
-
service 模块:
- 提供基本的服务管理功能,如启动、停止、重启和重新加载服务。
- name: Start a service service: name: my_service state: started
-
systemd 模块:
- 提供更高级的功能,如管理依赖关系、控制服务的启动顺序、定时器等。
- name: Start a systemd service systemd: name: my_service state: started
三、 3. 返回信息
-
service 模块:
- 返回的是传统服务管理的输出,适用于 SysVinit 和类似系统。
-
systemd 模块:
- 返回 systemd 相关的信息,提供更详细的状态和管理功能。
四、 4. 兼容性
- 在较新的 Linux 系统上,
systemd
模块更为常用和推荐,而在老旧系统或特定环境中,service
模块可能仍然有效。
五、 总结
如果你的目标系统使用 systemd,建议使用 systemd
模块,以便充分利用 systemd 提供的功能。如果系统较旧或不支持 systemd,则使用 service
模块。这样可以确保更好的兼容性和功能性。
systemd模块
具体使用?
To 验证???
user模块
具体使用?
To 验证???
- name: the play1
hosts: localhost
become: no
tasks:
- name: 创建组www
group:
name: www
gid: 666
tags: set_group
- name: 创建用户www
user:
name: www
uid: 666
# group: 666
group: www
shell: /sbin/nologin
tags: set_user
group模块
mount模块
具体使用?
To 验证???
unarchive模块
具体使用?
To 验证???
mysql_db模块
什么用
用于创建、删除和管理 MySQL 数据库。你可以通过该模块指定数据库的名称、字符集、排序规则等属性。
动作选项
确保目标主机有能够操控MySQL数据库的模块MySQL-python
否则,会有以下报错:下面的mysql_user模块也是一样的
测试
---
- name: The playbook to create database test_db
hosts: db01
become: no
tasks:
- name: to ensure the MySQL-python is installed in database server
yum:
name: MySQL-python
state: present
- name: to ensure the mariadb-server service is actived
service:
name: mariadb
state: started
- name: to create the database test_db
mysql_db:
login_user: root
login_password: 4439
name: test_db2
state: present
mysql_user模块
有什么用
用于创建、修改和删除 MySQL 用户。你可以设置用户的权限、主机限制、密码等属性。
动作选项
1、name
mysql里的数据库的用户
2、host
数据库访问的主机域
3、password
指定数据库访问的用户对应的密码
4、priv
指定权限(privileges),如:wp_db.*:ALL
5、login_user
启动mysql服务的登录用户(如果已设置了的话)
6、login_password
启动mysql服务的登录用户对应的密码
7、state
- present
- absent
测试:
管理机远程连接数据库服务器的数据库服务并设置库的登录用户
---
- name: the playbook to creat user of a database
hosts: db01
become: no
tasks:
- name: 确保安装Ansible需要连接数据库的Python服务
yum:
name: MySQL-python
state: present
- name: 确保已启动mariadb服务
service:
name: mariadb
state: started
- name: 设置test_db数据库的用户
mysql_user:
login_user: root
login_password: 4439
name: test_db_user1
host: '172.16.1.%'
password: 4439
priv: 'test_db.*:ALL'
# <==>
# mysql -u root -p4439
# create user 'test_db_user1'@'172.16.1.%' identified by '4439';
# grant all privileges on test_db.* to 'test_db_user1'@'172.16.1.%' with grant option;
debug模块
在 Ansible 的 debug
模块中,主要有以下几个属性:
-
msg:用于输出自定义消息,通常是调试信息或变量的值。
- debug: msg: "The value of var is {{ var }}"
在 Ansible 的
debug
模块中,msg
属性本身并没有定义子元素。它是一个简单的字符串,用于输出调试信息。你可以通过Jinja2 表达式在msg
中插入变量或表达式来丰富输出。不过,在更复杂的用法中,你可能会遇到以下情境:
- 变量输出:直接引用变量。
- debug: msg: "Value: {{ my_variable }}"
- 字典和列表:输出字典或列表的内容。
- debug: msg: "List items: {{ my_list }}"
- 条件表达式:结合条件语句。
- debug: msg: "{{ 'Condition is true' if condition else 'Condition is false' }}"
- 格式化输出:使用格式化方法来创建复杂消息。
- debug: msg: "User: {name}, Age: {age}".format(name=my_user.name, age=my_user.age)
虽然
msg
本身没有子元素,但可以通过灵活使用 Jinja2 表达式来构建复杂的调试输出。
-
var:用于直接输出变量的值。
- debug: var: my_variable
-
verbosity:设置输出的详细级别。可以使用的值为
1
到4
,默认为1
。较高的级别会输出更多的信息。- debug: msg: "This is a detailed message" verbosity: 2
-
verbosity:设置输出的详细级别。可以使用的值为
1
到4
,默认为1
。较高的级别会输出更多的信息。- debug: msg: "This is a detailed message" verbosity: 2
这些属性允许你在调试 Ansible playbook 时输出有用的信息,帮助你更好地理解任务执行的过程。
set_fact模块
ToDo Here????
setup模块
ToDo Here???
get_url模块
get_url
模块用于从指定的URL下载文件。基本用法如下:
- name: Download a file
get_url:
url: https://example.com/file.zip
dest: /path/to/destination/file.zip
checksum: "sha256:your_checksum_here" # 可选,用于验证文件完整性
force: yes # 可选,强制下载
参数说明:
- url:要下载的文件的URL。
- dest:保存下载文件的目标路径。
- checksum:可选,用于确保文件的完整性。
- force:可选,设置为
yes
时,即使文件已存在也会重新下载。
可搭配循环实现下载多个文件:
template模块
在 Ansible 的 playbooks 或任务中,经常需要使用 template
模块来处理模板文件。这个模块允许你定义一个源文件,这个文件包含了 Jinja2 模板语法,然后 Ansible会将这个模板渲染成最终的配置文件,并将其传输到目标主机上。
ToDo Here???
archive模块
archive
模块用于创建压缩文件(如ZIP或TAR)。以下是其基本用法及示例:
---
- name: Create an archive using Ansible
hosts: localhost
tasks:
- name: Create a tar.gz archive
archive:
path:
- /path/to/directory1
- /path/to/file1.txt
dest: /path/to/archive.tar.gz
format: gz # 指定压缩格式,可以是 tar, gz, zip 等
force: yes # 可选,强制覆盖已存在的归档文件
- path:要归档的文件或目录的列表。
- dest:生成的压缩文件的目标路径。
- format:可选,指定归档格式(如
tar
,gz
,zip
等)。 - force:可选,设置为
yes
时会覆盖已有的归档文件。 - remove: 压缩后,删除源文件
将以上内容保存到 archive_example.yml
文件中,然后执行:
ansible-playbook archive_example.yml
cron模块
在 Ansible 中,cron
模块用于管理 Linux 系统的 cron 作业。它可以添加、删除或修改定时任务。
一、 基本用法
cron
模块的主要参数包括:
name
:任务的描述,用于标识作业。minute
,hour
,day
,month
,weekday
:定义何时运行作业的时间设置。job
:要执行的命令或脚本。state
:指定作业的状态,可以是present
(存在)或absent
(不存在)。user
:指定执行该 cron 作业的用户。
二、 示例
以下是几个使用 cron
模块的示例:
示例 1:添加一个新的 cron 作业
- name: Add a cron job to run a script every day at 2 AM
hosts: all
tasks:
- name: Create cron job
cron:
name: "Run daily backup"
minute: "0"
hour: "2"
job: "/usr/local/bin/backup.sh"
state: present
示例 2:删除现有的 cron 作业
- name: Remove a cron job
hosts: all
tasks:
- name: Delete cron job
cron:
name: "Run daily backup"
state: absent
示例 3:以特定用户创建 cron 作业
- name: Add a cron job for a specific user
hosts: all
tasks:
- name: Create cron job for user 'deploy'
cron:
name: "Run cleanup script"
minute: "0"
hour: "3"
job: "/usr/local/bin/cleanup.sh"
user: deploy
state: present
三、 参数详解
- name:此项是必需的,提供一个易于识别的名称,便于后续维护。
- minute:指定分钟(0-59),可以使用逗号分隔多个值,例如
0,30
,或使用*
表示每分钟。 - hour:指定小时(0-23)。
- day:指定日期(1-31)。
- month:指定月份(1-12)。
- weekday:指定星期几(0-7,0和7都表示星期日)。
- job:实际要执行的命令,可以是任何有效的 shell 命令。
- state:设置为
present
以添加作业,设置为absent
以删除作业。 - user:可选,指定要为哪个用户创建作业。如果未指定,默认是当前用户。
四、 注意事项
- 确保命令的路径是绝对路径,以避免找不到命令的问题。
- 如果需要输出日志,可以在
job
中重定向输出,例如:job: "/usr/local/bin/backup.sh >> /var/log/backup.log 2>&1"
。 - 使用适当的权限来创建和管理 cron 作业,确保用户有权限执行相关的命令。