Ansible教程:Ad-hoc 命令用法-shell模块 作者:马育民 • 2026-09-21 08:18 • 阅读:10001 # 介绍 在远程主机通过 **shell(默认 /bin/sh)** 执行命令,**支持管道 `|`、重定向 `> >>`、`&`、shell变量、通配符** 模块全名:`ansible.builtin.shell`(2.10+集合命名,旧版直接写 `shell`) # 参数 | 参数 | 说明 | |---|---| | cmd | 要执行的shell命令;playbook中也可以直接写命令(free_form写法,没有free_form这个真实参数) | | chdir | 执行命令前,先切换到该目录 | | creates | 文件路径:**如果文件已存在,则跳过本次任务**(做幂等) | | removes | 文件路径:**如果文件不存在,则跳过本次任务** | | executable | 指定shell解释器绝对路径,例 `/bin/bash`;默认 `/bin/sh` | | stdin | 设置命令标准输入 | | stdin_add_newline | bool,默认yes;是否给stdin末尾追加换行符 | | warn | bool,默认yes;是否开启ansible对shell模块的警告(长命令建议关闭) | > 返回结果字段:`rc` 返回码、`stdout` 标准输出、`stderr` 错误输出、`stdout_lines` 输出按行列表。 # Ad-hoc 命令用法 ```bash # 基础:查看主机名(单引号,变量在远程解析) ansible web -m shell -a 'echo $HOSTNAME' # 管道过滤进程 ansible web -m shell -a 'ps aux | grep nginx | grep -v grep' # chdir:先cd到/var/log,执行ls ansible web -m shell -a 'ls' -a chdir=/var/log # creates:/tmp/ok.txt存在,就不执行 ansible web -m shell -a 'touch /tmp/ok.txt' -a creates=/tmp/ok.txt # 指定bash执行 ansible web -m shell -a 'echo $BASH_VERSION' executable=/bin/bash ``` # shell vs command 比较 | 模块 | 执行方式 | 支持管道/重定向 | 幂等性 | 推荐 | |---|---|---|---|---| | shell | 拉起shell进程执行 | ✅ 支持 | ❌ 命令本身不幂等 | 复杂命令、管道、脚本 | | command | exec直接执行程序,不经过shell | ❌ 不支持 ` >` 等管道 | ❌ | 简单命令,优先使用,更安全 | 原则:**能使用command就不用shell**,shell有shell注入风险。 # 注意事项 ### 1. **幂等性问题** shell模块本身**不具备幂等**。多次执行可能重复操作。 用 `creates/removes` + `changed_when` 来模拟幂等: ```yaml shell: touch /tmp/xxx args: creates: /tmp/xxx ``` ### 2. **引号坑(Ad-hoc)** - 单引号 `'echo $var'`:变量在远程主机解析 ✅ - 双引号 `"echo $var"`:变量在**本地ansible主机解析** ❌ ### 3. 多行shell脚本:`|` yaml多行字符串 ```yaml - name: 多行脚本 shell: | set -e echo "start" ls /tmp echo "done" args: executable: /bin/bash ``` ### 4. 安全风险 shell会做命令替换,**不要直接传入不可信外部变量**,防止shell注入。 ### 5. 换行、特殊字符 复杂命令建议用 `args` 拆分,或者放到脚本文件用 `script` 模块。 # 常见返回值判断 ```yaml - name: run cmd shell: cat /etc/hosts register: out failed_when: out.rc !=0 # out.stdout 字符串 # out.stdout_lines 数组 # out.stderr 错误信息 # out.rc 返回码,0成功 ``` # shell / script / raw 简要区分 - `shell`:远程主机调用shell执行一段命令;支持`become`、环境变量 - `script`:把**本地控制节点脚本**上传到远程执行,不需要shell语法 - `raw`:底层ssh直接执行,**不支持become、async、环境变量**;无python环境时用 # 最佳实践 1. 简单命令优先 `command`;必须管道/重定向才选 `shell` 2. shell任务尽量加 `changed_when: false`(查询类)或 `creates`(修改类)减少误报changed 3. 长脚本,优先把脚本文件分发后用 `script`,不要写超大多行shell 4. 指定bash时使用 `executable: /bin/bash`,因为 `/bin/sh` 不支持bash特有语法 原文出处:/show_1GW45R4T4PoP.html