如何使用 grep、awk、sed 在 ansible 任务中放置引号

How to place quotes mark in ansible task with grep, awk, sed

我的任务是在 CMD 列中搜索配置以收集应用程序配置目录和 PID 的信息。

---
- hosts: all
  pre_tasks:
    - name: Check if process is running
      become: yes
      shell: 'ps -e --format="pid cmd" | grep process.cfg | sed -e "s/[[:space:]]\+/ /g"| grep -v color'
      register: proces_out

执行此命令后输出如下所示:

32423 /var/local/bin/application -c /var/local/etc/process.cfg

但我认为 ansible 在 1 个命令中使用 2 个 greps 有问题。我需要它们,因为如果我不使用反向 "grep -v color",这个烦人的事情就会出现 "grep --color=auto ",我无法在另一个杀死进程的任务中删除我需要的 PID,因为真正的进程在第二行。

我的第二个想法是使用 AWK,我认为这对这种情况来说是最好的工具,但是如果我在 --format 参数和 SED 命令中使用双引号,在 awk 参数中使用单引号,它们不想合作。即使我让他们保持平衡,他们也会干扰他们自己。

AWK 理念:

shell: 'ps -e --format="pid cmd" | grep process.cfg | sed -e "s/[[:space:]]\+/ /g"| awk 'FNR == 2''

我想请教一下什么是最好的避免代码不兼容并能够在变量

中作为输出使用它的方法
## PID
{{ proces_out.stdout.split(' ')[0] }} 
## application
{{ proces_out.stdout.split(' ')[1] }}
## config
{{ proces_out.stdout.split(' ')[3] }}

But i think ansible have troubles with 2 greps in 1 command

那是肯定不正确

if i dont use reversed "grep -v color" this anoying thing appears "grep --color=auto ", i cant cut out PID that i need in another task which kills process because real process is in second line.

您正在 运行 进入 grep 进程匹配其自己的正则表达式的经典案例,这在很多 "simple" 案例中都会发生。你想要的是一个匹配你的字符串但不匹配自身的正则表达式。在上面的例子中它将是:

  shell: 'ps -e --format="pid cmd" | grep process[.]cfg | sed -e "s/[[:space:]]\+/ /g"'

因为 process[.]cfg 匹配 process.cfg 但不匹配 process[.]cfg 我还修复了你的正则表达式,因为在正则表达式中, . 表示任何字符,它不似乎是你真正想要发生的事情

关于 --color 位,您可能可以通过使用 grep 的完整路径来回避这些废话,这将导致 bash 真正执行二进制文件, 而不是一些使用 --color=auto 的别名;我实际上不希望颜色出现在 ansible 运行 中,因为它不正确 $TERM 但系统很奇怪

谢谢 Matthew 提供的解决方案,但我找到了不同的选项来避免不必要的输出。 所以语法几乎相同,但我添加到 --format 附加参数 ppid 父进程 ID,在大多数情况下,我相信父进程在输出中总是有数字 1,这有助于按照我的意愿对其进行排序。

看起来像这样:

  shell: >
    ps -e --format="ppid pid cmd" |
    grep process.cfg |
    sed -e "s/[[:space:]]\+/ /g"
  register: output_process

输出如下所示:

 1 54345 /var/local/bin/application -c /var/local/etc/process.cfg
6435 6577 grep --color=auto process.cfg

现在很容易我们可以使用 ansible 模块对其进行排序:

- name: Kill process
  become: yes
  shell: "kill {{ output_process.stdout_lines[0].split(' ')[2] }}"

它有什么作用?它选择第一行的第 0 行,在空格之间拆分输出并选择第三个短语。在输出 ppid 之前有 :space: 这就是为什么 PID 是第 3

再次感谢您的解决方案 Matthew,在其他情况下可能会有所帮助。