无法用Ansible copy模块将变量值追加到文件的问题求助
问题背景
从数据库脚本输出的示例数据(格式不可控)存储在junk.txt中,内容如下:
{:,:"(s):"}}
尝试通过Ansible Playbook将该数据写入github.out并持续追加,但遇到两个问题:
1. raw/shell模块写入时触发语法错误
取消注释raw模块写入任务后,出现shell语法错误:
TASK [Dump data to file]
Monday 27 November 2023 10:21:22 -0600 (0:00:00.035)
0:00:00.087 *******
fatal: [localhost]: FAILED! => {"changed": true, "msg": "non-zero return code", "rc": 1, "stderr": "/bin/sh: -c: line 0: syntax error near unexpected token('\n/bin/sh: -c: line 0:echo "{:,:"(s):"}}'\n", "stderr_lines": ["/bin/sh: -c: line 0: syntax error near unexpected token('", "/bin/sh: -c: line 0:echo "{:,:"(s):"}}'"], "stdout": "", "stdout_lines": []}
原因是数据包含引号、括号等特殊字符,直接在shell命令中展开会被解析为语法结构,导致报错。
2. copy模块无法实现内容追加
使用copy模块时,即使设置force: no,第二次写入也不会追加内容,最终github.out仅保留第一次写入的结果,无法达到如下期望输出:
$ cat github.out >> TXT SUCCESS OUTPUT1- {:,:"(s):"}} >> TXT SUCCESS OUTPUT2- {:,:"(s):"}}
解决方案
方案1:修复shell/raw模块的语法错误
通过quote过滤器对特殊字符进行安全转义,避免shell解析错误:
- name: Read junk file raw: "cat {{ playbook_dir }}/junk.txt" register: junkdata - name: Dump data to file (修复语法错误) ansible.builtin.shell: | echo {{ junkdata.stdout | quote }} >> "{{ playbook_dir }}/github.out"
或者使用printf进一步降低转义风险:
- name: Dump data to file (更安全的printf方式) ansible.builtin.shell: | printf "%s\n" {{ junkdata.stdout | quote }} >> "{{ playbook_dir }}/github.out"
方案2:使用Ansible原生模块实现安全追加(推荐)
用slurp模块读取文件(避免shell命令的额外问题),再用lineinfile模块将内容追加到文件末尾,无需处理shell转义:
--- - name: "Play 1-Find the details here" hosts: localhost gather_facts: no tasks: - name: Read junk file content ansible.builtin.slurp: src: "{{ playbook_dir }}/junk.txt" register: junkdata - name: Append OUTPUT1 to github.out ansible.builtin.lineinfile: path: "{{ playbook_dir }}/github.out" line: ">> TXT SUCCESS OUTPUT1- {{ junkdata.content | b64decode | trim }}" insertafter: EOF create: yes # 文件不存在时自动创建 - name: Append OUTPUT2 to github.out ansible.builtin.lineinfile: path: "{{ playbook_dir }}/github.out" line: ">> TXT SUCCESS OUTPUT2- {{ junkdata.content | b64decode | trim }}" insertafter: EOF
slurp模块通过base64编码读取文件内容,避免特殊字符传递时的问题,读取后用b64decode解码,trim去除可能的换行符。lineinfile的insertafter: EOF参数确保内容追加到文件末尾,create: yes自动创建不存在的目标文件。
内容的提问来源于stack exchange,提问作者Ashar

