shell模块可引用环境变量,command模块不可;前者通过/bin/sh -c执行并加载profile等配置,支持管道、重定向等shell特性,后者绕过shell直接调用程序,更安全但不支持变量和复杂操作符。

在Ansible部署中,能否正确引用环境变量,关键取决于你用的是 command 还是 shell 模块——它们对环境变量的处理方式完全不同。
command模块:不加载环境,变量不可用
command模块绕过shell,直接调用程序执行。它不会读取 /etc/profile、~/.bashrc 或当前用户的环境配置,因此像 $HOME、$PATH、$JAVA_HOME 这类变量在命令中一律为空或未定义。
- 执行
ansible web -m command -a "echo $HOME",结果通常是空行 - 重定向(
>)、管道(|)、逻辑运算(&&)会被当作字面参数传给命令,而非由shell解析 - 适合执行简单、确定路径的命令,比如
systemctl status nginx或/usr/bin/python3 --version
shell模块:完整shell环境,变量可直接引用
shell模块通过 /bin/sh -c 启动一个真实shell进程,会加载系统级和用户级的初始化文件(取决于目标用户权限),因此所有已定义的环境变量均可在命令中使用。
-
ansible web -m shell -a "echo $HOME"能正确输出如/root或/home/deploy - 支持
ls /tmp | grep log、export PATH=/opt/bin:$PATH && mytool --help等复合操作 - 注意:若目标用户是非交互式登录(如 ansible 默认用 root 或普通用户 ssh 登录),
~/.bashrc可能未被加载;建议显式 source 或改用executable: /bin/bash
安全引用变量的实操要点
当命令中需插入 Ansible 变量(如 {{ app_home }})并配合 shell 特性时,必须防范注入风险:
- 错误写法:
- shell: "cd {{ app_home }} && ./start.sh"—— 若app_home含分号或空格,可能执行意外命令 - 正确写法:
- shell: "cd {{ app_home | quote }} && ./start.sh"——| quote会自动加引号并转义特殊字符 - 更稳妥做法:优先用
chdir参数代替cd,例如- shell: "./start.sh" chdir: "{{ app_home }}"
部署场景下的选型建议
不要为了“方便”默认全用 shell;应按实际需求判断:
- 只需运行单个二进制、不依赖上下文:坚持用
command,更安全、更可预测 - 需要
$PATH查找工具、依赖$JAVA_HOME启动服务、或组合多条命令:必须用shell,并确保目标用户环境已就绪 - 涉及复杂逻辑(如条件启动、状态检查后执行):考虑改用
community.general.shell或原生模块(如systemd、pip、yum),它们自带环境适配与幂等性











