You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ansible中正确编写awk命令?解决模板语法报错问题

问题描述

终端中可正常运行的awk命令如下:

awk '/java/ {print "PID is:" $2"
Process Dump is:	" $0}' <(ps -ef | grep -v grep)

执行后输出示例:

PID is:515
Process Dump is:    wladmin    515   506  0 Nov03 ?        01:11:39 /web/jdk-18.0.1.1/bin/java -jar remoting.jar -workDir /web/jenkinsprod -jar-cache /web/jenkinsprod/remoting/jarCache
PID is:22145
Process Dump is:    wladmin  22145 22140  0 Nov04 ?        00:54:18 /web/jdk-18.0.1.1/bin/java -Djava.io.tmpdir=/web/jenkins_windows/tmp -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -jar remoting.jar -workDir /web/jenkins_windows -jar-cache /web/jenkins_windows/remoting/jarCache
PID is:32703
Process Dump is:    wladmin  32703 32699  0 Nov03 ?        01:10:34 /web/jdk-18.0.1.1/bin/java -Djava.io.tmpdir=/web/jenkins/tmp -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -jar remoting.jar -workDir /web/jenkins -jar-cache /web/jenkins/remoting/jarCache

尝试将该命令整合到Ansible中,生成包含java和ssh两个匹配项的命令列表,编写的Playbook如下:

---

- name: Concant and Print variable
  gather_facts: false
  hosts: localhost
  tasks:
    - name: Test
      set_fact:
        process_dump: "{{ process_dump  | default([]) +  ['awk \'/\" ~ item ~ \"/ {print \"PID is:\" $2\"\nProcess Dump is:\t\" $0}\' <(ps -ef | grep -v grep)'] }}"
      loop:
        - 'java'
        - 'ssh'

    - debug:
        msg: "{{ item }}"
      loop: "{{ process_dump }}"

    - command: "{{ item }}"
      loop: "{{ process_dump }}"

执行时触发模板错误:

TASK [Test] ****************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: expected token ':', got 'string'. String: {{ process_dump  | default([]) +  ['awk '/' ~ item ~ '/ {print \"PID is:\" $2\"\nProcess Dump is:\t\" $0}' <(ps -ef | grep -v grep)'] }}"}
错误原因
  • Jinja2模板转义冲突:set_fact中的字符串拼接逻辑混乱,单双引号转义错误,导致模板引擎无法正确识别语法边界,误判字符串结束位置。
  • command模块不支持shell特性:原命令使用了<()进程替换(bash专属特性),但command模块直接执行命令,不经过shell解析,无法识别该语法。
  • 复杂拼接易出错:直接在Jinja2表达式中拼接带特殊字符的命令,可读性差且极易出现转义失误。
正确的Ansible配置

提供两种可行的修正方案:

方案一:直接在任务中执行(简洁版)

---

- name: Collect process dumps
  gather_facts: false
  hosts: localhost
  tasks:
    - name: Execute process check commands
      shell: |
        awk '/{{ item }}/ {print "PID is:" $2"\nProcess Dump is:\t" $0}' <(ps -ef | grep -v grep)
      loop:
        - 'java'
        - 'ssh'
      register: process_dump_results

    - name: Print process dumps
      debug:
        msg: "{{ item.stdout }}"
      loop: "{{ process_dump_results.results }}"

方案二:提前构造命令列表(可复用版)

---

- name: Collect process dumps
  gather_facts: false
  hosts: localhost
  tasks:
    - name: Build command list
      set_fact:
        process_dump_commands: "{{ process_dump_commands | default([]) + [command] }}"
      vars:
        command: "awk '/{{ item }}/ {print \"PID is:\" $2\"\\nProcess Dump is:\\t\" $0}' <(ps -ef | grep -v grep)"
      loop:
        - 'java'
        - 'ssh'

    - name: Show commands
      debug:
        msg: "{{ item }}"
      loop: "{{ process_dump_commands }}"

    - name: Execute commands
      shell: "{{ item }}"
      loop: "{{ process_dump_commands }}"
      register: process_dump_results

    - name: Print results
      debug:
        msg: "{{ item.stdout }}"
      loop: "{{ process_dump_results.results }}"

修改说明

  • 替换command模块为shell模块,支持bash的进程替换特性。
  • 用Jinja2变量{{ item }}直接注入匹配项,规避复杂的字符串拼接转义。
  • 用register捕获命令执行结果,方便后续输出或二次处理。
  • 将换行符\n转义为\\n、制表符\t转义为\\t,确保Jinja2解析后能正确传递给shell。

内容的提问来源于stack exchange,提问作者Ashar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:35:22