如何用Ansible将含特殊字符的命令行内容复制到文件?
解决Ansible命令行传递含特殊字符脚本的问题
问题场景
需要通过Ansible在多节点运行**动态变化且包含特殊字符(如单引号)**的脚本,使用--extra-vars传递脚本内容时,因shell的引号解析规则导致执行失败。原Playbook及执行命令如下:
原Playbook
--- - hosts: all become: true tasks: - name: copy extra variables to a file copy: content: | {{ command }} dest: /tmp/commands.sh delegate_to: localhost - name: copy commands.sh to nodes copy: src: /tmp/commands.sh dest: /tmp/ mode: 0755 - name: run the commands in the nodes shell: /bin/bash /tmp/commands.sh register: command_output - name: print output debug: msg: "{{ command_output.stdout_lines }}"
原执行命令(存在问题)
ansible-playbook -i hosts.ini store-in-file-and-run-in-nodes.yaml -e "command=' date ps -ef | grep httpd echo "That's all folks" ' "
上述命令因echo "That's all folks"中的单引号导致shell解析中断,无法完整传递脚本内容。
解决方案
方案1:使用JSON格式传递--extra-vars
bash对单引号嵌套的处理非常繁琐,改用JSON格式定义变量可以绕过shell的引号解析问题,完整保留脚本内容:
多行JSON写法(推荐)
ansible-playbook -i hosts.ini store-in-file-and-run-in-nodes.yaml -e @- <<EOF { "command": "date ps -ef | grep httpd echo \"That's all folks\"" } EOF
通过@-读取标准输入的JSON内容,脚本中的特殊字符无需额外转义,直接原样写入即可。
单行JSON写法
ansible-playbook -i hosts.ini store-in-file-and-run-in-nodes.yaml -e '{"command": "date\nps -ef | grep httpd\necho \"That'\''s all folks\""}'
注意:单行JSON中换行需用\n表示,内部单引号需用'\''转义(适合短脚本)。
方案2:通过本地文件传递脚本内容
如果脚本内容较长或特殊字符较多,直接在命令行输入不便,可以将脚本变量定义写入本地文件,再通过--extra-vars引用:
- 创建
script_vars.yaml文件,内容如下:
command: | date ps -ef | grep httpd echo "That's all folks"
- 执行Playbook时引用该文件:
ansible-playbook -i hosts.ini store-in-file-and-run-in-nodes.yaml -e "@script_vars.yaml"
这种方式完全避免了命令行的引号问题,脚本内容可原样保存。
方案3:简化Playbook流程(跳过本地临时文件)
原Playbook中先在localhost生成脚本再复制到节点的步骤可以简化,直接在目标节点创建脚本文件,减少中间环节:
修改后的Playbook:
--- - hosts: all become: true tasks: - name: Create script file on target nodes copy: content: "{{ command }}" dest: /tmp/commands.sh mode: 0755 - name: Run the script shell: /bin/bash /tmp/commands.sh register: command_output - name: Print output debug: msg: "{{ command_output.stdout_lines }}"
配合方案1或方案2的变量传递方式,可高效完成脚本分发与执行。
内容的提问来源于stack exchange,提问作者Krish R
相关产品推荐
相关产品推荐

