在 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 功能。