Ansible教程:Ad-hoc 命令用法-shell模块

介绍

在远程主机通过 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 命令用法

基础:查看主机名

单引号,变量在远程解析

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 来模拟幂等:

shell: touch /tmp/xxx
args:
  creates: /tmp/xxx

2. 引号坑(Ad-hoc)

  • 单引号 'echo $var':变量在远程主机解析 ✅
  • 双引号 "echo $var":变量在本地ansible主机解析 ❌

3. 多行shell脚本:| yaml多行字符串

 - name: 多行脚本
  shell: |
    set -e
    echo "start"
    ls /tmp
    echo "done"
  args:
    executable: /bin/bash

4. 安全风险

shell会做命令替换,不要直接传入不可信外部变量,防止shell注入。

5. 换行、特殊字符

复杂命令建议用 args 拆分,或者放到脚本文件用 script 模块。

常见返回值判断

- 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