在 Ansible 中,command 和 shell 模块都用于在目标主机上执行命令,但它们在功能和行为上有显著的区别。了解这些区别可以帮助你更安全、更有效地编写 Playbook。
command 模块
特点:
- 绕过 Shell:
command模块直接执行命令,绕过目标主机的 Shell(如 bash、zsh 或 sh)。 - 不支持 Shell 功能:不支持变量展开、重定向、管道、条件判断等 Shell 内置功能。
- 安全性更高:由于绕过了 Shell,
command模块的行为更可预测,安全性更高。 - 返回状态:无论命令是否成功,
command模块始终将changed设置为True。
适用场景:
- 执行简单的二进制命令,如
uptime、date等。 - 当不需要 Shell 功能时,优先使用
command模块。
示例代码:
---
- name: command module demo
hosts: all
tasks:
- name: check uptime
ansible.builtin.command: uptime
register: command_output
- name: command output
ansible.builtin.debug:
var: command_output.stdout_lines
执行结果:
PLAY [command module demo] ***********************************
TASK [Gathering Facts] ***************************************
ok: [demo.example.com]
TASK [check uptime] *******************************************
changed: [demo.example.com]
TASK [command output] *****************************************
ok: [demo.example.com] => {
"command_output.stdout_lines": [
" 12:51:34 up 8 min, 1 user, load average: 0.00, 0.05, 0.06"
]
}
PLAY RECAP ***************************************************
demo.example.com : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
shell 模块
特点:
- 支持 Shell 功能:
shell模块通过目标主机的 Shell 执行命令,支持变量展开、重定向、管道、条件判断等 Shell 内置功能。 - 灵活性更高:可以执行复杂的命令组合,如
ls -l | grep something。 - 安全性较低:由于使用了 Shell,
shell模块的行为可能不如command模块可预测,存在注入风险。 - 返回状态:无论命令是否成功,
shell模块始终将changed设置为True。
适用场景:
- 需要使用 Shell 功能时,如变量展开、重定向、管道等。
- 执行复杂的命令组合。
示例代码:
---
- name: shell module demo
hosts: all
tasks:
- name: list file(s) and folder(s)
ansible.builtin.shell: 'ls -l *'
register: command_output
- name: command output
ansible.builtin.debug:
var: command_output.stdout_lines
执行结果:
PLAY [shell module demo] *************************************
TASK [Gathering Facts] ***************************************
ok: [demo.example.com]
TASK [list file(s) and folder(s)] *****************************
changed: [demo.example.com]
TASK [command output] *****************************************
ok: [demo.example.com] => {
"command_output.stdout_lines": [
"-rwxr-xr-x. 1 devops wheel 31 Mar 30 13:39 example.sh"
]
}
PLAY RECAP ***************************************************
demo.example.com : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
错误使用示例
如果错误地使用了 command 模块执行需要 Shell 功能的命令,可能会导致失败:
错误代码:
---
- name: shell module demo
hosts: all
tasks:
- name: list file(s) and folder(s)
ansible.builtin.command: 'ls -l *'
register: command_output
- name: command output
ansible.builtin.debug:
var: command_output.stdout_lines
执行结果:
PLAY [shell module demo] *************************************
TASK [Gathering Facts] ***************************************
ok: [demo.example.com]
TASK [list file(s) and folder(s)] *****************************
fatal: [demo.example.com]: FAILED! => {"changed": true, "cmd": ["ls", "-l", "*"], "delta": "0:00:00.003038", "end": "2022-04-06 13:01:54.498403", "msg": "non-zero return code", "rc": 2, "start": "2022-04-06 13:01:54.495365", "stderr": "ls: cannot access '*': No such file or directory", "stderr_lines": ["ls: cannot access '*': No such file or directory"], "stdout": "", "stdout_lines": []}
PLAY RECAP ***************************************************
demo.example.com : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
总结
command模块:- 优点:安全性高,行为可预测。
- 缺点:不支持 Shell 功能。
- 适用场景:执行简单的二进制命令。
shell模块:- 优点:支持 Shell 功能,灵活性高。
- 缺点:安全性较低,存在注入风险。
- 适用场景:需要使用 Shell 功能时。
建议:
- 尽量避免使用
command或shell模块,优先使用 Ansible 提供的专门模块(如ansible.builtin.copy、ansible.builtin.file等)。 - 如果必须使用,优先选择
command模块,除非确实需要 Shell 功能。