如何将Ansible的’stdout_lines’输出存储在字典中?

huangapple go评论56阅读模式
英文:

How to store Ansible 'stdout_lines' output in a dictionary?

问题

我有以下的Ansible代码片段,用于打印进程的PID和名称。

- name: 获取所有运行中的进程
  shell:
    cmd: pgrep -a run.sh
  register: _get_pid_and_name

- name: 打印PID详细信息
  debug:
    msg: "{{ _get_pid_and_name.stdout }}"

上述任务以以下格式输出结果。

"msg": [
 1234223 /bin/ksh ./run.sh -f -i 1
 4356223 /bin/ksh ./run.sh -f -i 2
 887455 /bin/ksh ./run.sh -f -i 3
 9934534 /bin/ksh ./run.sh -f -i 4
 3245764 /bin/ksh ./run.sh -f -i 5
]

我需要从上述输出中提取PID和名称。

英文:

I have below Ansible snippet that print PIDs and name of process.

- name: Get all running processes
  shell:
    cmd: pgrep -a run.sh
  register: _get_pid_and_name

- name: Print PID details
  debug:
    msg: "{{ _get_pid_and_name.stdout }}"

Above task prints output in below format

"msg": [
 1234223 /bin/ksh ./run.sh -f -i 1
 4356223 /bin/ksh ./run.sh -f -i 2
 887455 /bin/ksh ./run.sh -f -i 3
 9934534 /bin/ksh ./run.sh -f -i 4
 3245764 /bin/ksh ./run.sh -f -i 5
]

I need to extract PID and name from the above output.

答案1

得分: 1

创建以下用于测试的脚本

shell> cat run.sh
#!/bin/sh

cat << EOM
1234223 /bin/ksh ./run.sh -f -i 1
4356223 /bin/ksh ./run.sh -f -i 2
887455 /bin/ksh ./run.sh -f -i 3
9934534 /bin/ksh ./run.sh -f -i 4
3245764 /bin/ksh ./run.sh -f -i 5
EOM

运行脚本并注册输出以供测试使用

    - script: run.sh
      register: get_pid_and_name

分割字段

  arr: "{{ get_pid_and_name.stdout_lines|map('split') }}"

得到

  arr:
    - ['1234223', /bin/ksh, ./run.sh, -f, -i, '1']
    - ['4356223', /bin/ksh, ./run.sh, -f, -i, '2']
    - ['887455', /bin/ksh, ./run.sh, -f, -i, '3']
    - ['9934534', /bin/ksh, ./run.sh, -f, -i, '4']
    - ['3245764', /bin/ksh, ./run.sh, -f, -i, '5']

创建字典

  pid_name: |
    {% filter from_yaml %}
    {% for i in arr %}
    {{ i.0 }}: {{ i.1 }}
    {% endfor %}
    {% endfilter %}    

得到

  pid_name:
    887455: /bin/ksh
    1234223: /bin/ksh
    3245764: /bin/ksh
    4356223: /bin/ksh
    9934534: /bin/ksh

获取 PIDname 的列表

  pids: "{{ pid_name.keys()|list }}"
  names: "{{ pid_name.values()|list }}"

得到

  pids: [1234223, 4356223, 887455, 9934534, 3245764]
  names: [/bin/ksh, /bin/ksh, /bin/ksh, /bin/ksh, /bin/ksh]

注意:

  • 有许多其他选项可以获取这些列表。例如,
  pids: "{{ arr|map('first')|map('int')|list }}"
  pids: "{{ arr|json_query('map(&[0], @)') }}"
  names: "{{ arr|json_query('map(&[1], @)') }}"

  • 完整的测试用例示例
- hosts: localhost

  vars:

    arr: "{{ get_pid_and_name.stdout_lines|map('split') }}"
    pid_name: |
      {% filter from_yaml %}
      {% for i in arr %}
      {{ i.0 }}: {{ i.1 }}
      {% endfor %}
      {% endfilter %}      
    pids: "{{ pid_name.keys()|list }}"
    names: "{{ pid_name.values()|list }}"

  tasks:

    - script: run.sh
      register: get_pid_and_name

    - debug:
        var: arr|to_yaml
    - debug:
        var: pid_name
    - debug:
        var: pids|to_yaml
    - debug:
        var: names|to_yaml

英文:

Create the below script for testing

shell> cat run.sh
#!/bin/sh

cat << EOM
1234223 /bin/ksh ./run.sh -f -i 1
4356223 /bin/ksh ./run.sh -f -i 2
887455 /bin/ksh ./run.sh -f -i 3
9934534 /bin/ksh ./run.sh -f -i 4
3245764 /bin/ksh ./run.sh -f -i 5
EOM

Run the script and register the output for testing

    - script: run.sh
      register: get_pid_and_name

Split the fields

  arr: "{{ get_pid_and_name.stdout_lines|map('split') }}"

gives

  arr:
    - ['1234223', /bin/ksh, ./run.sh, -f, -i, '1']
    - ['4356223', /bin/ksh, ./run.sh, -f, -i, '2']
    - ['887455', /bin/ksh, ./run.sh, -f, -i, '3']
    - ['9934534', /bin/ksh, ./run.sh, -f, -i, '4']
    - ['3245764', /bin/ksh, ./run.sh, -f, -i, '5']

Create dictionary

  pid_name: |
    {% filter from_yaml %}
    {% for i in arr %}
    {{ i.0 }}: {{ i.1 }}
    {% endfor %}
    {% endfilter %}    

gives

  pid_name:
    887455: /bin/ksh
    1234223: /bin/ksh
    3245764: /bin/ksh
    4356223: /bin/ksh
    9934534: /bin/ksh

Get the lists of PID and name

  pids: "{{ pid_name.keys()|list }}"
  names: "{{ pid_name.values()|list }}"

gives

  pids: [1234223, 4356223, 887455, 9934534, 3245764]
  names: [/bin/ksh, /bin/ksh, /bin/ksh, /bin/ksh, /bin/ksh]

<hr>

<sup>

Notes:

  • There is plenty of other options on how to get the lists. For example,
  pids: &quot;{{ arr|map(&#39;first&#39;)|map(&#39;int&#39;)|list }}&quot;
  pids: &quot;{{ arr|json_query(&#39;map(&amp;[0], @)&#39;) }}&quot;
  names: &quot;{{ arr|json_query(&#39;map(&amp;[1], @)&#39;) }}&quot;

<hr>

  • Example of a complete playbook for testing
- hosts: localhost

  vars:

    arr: &quot;{{ get_pid_and_name.stdout_lines|map(&#39;split&#39;) }}&quot;
    pid_name: |
      {% filter from_yaml %}
      {% for i in arr %}
      {{ i.0 }}: {{ i.1 }}
      {% endfor %}
      {% endfilter %}      
    pids: &quot;{{ pid_name.keys()|list }}&quot;
    names: &quot;{{ pid_name.values()|list }}&quot;

  tasks:

    - script: run.sh
      register: get_pid_and_name

    - debug:
        var: arr|to_yaml
    - debug:
        var: pid_name
    - debug:
        var: pids|to_yaml
    - debug:
        var: names|to_yaml

</sup>

答案2

得分: 0

我需要从上述输出中提取PID和名称。

由于您已经知道进程的名称,并且您只想查找它,因此名称已知,您只需要提取PID。

对于更通用的如何拆分stdout_lines并将其转换为字典,您可以直接使用这里已经提供的答案。

另一种方法是使用jc过滤器 - 将许多Shell命令和文件类型的输出转换为JSON,也许还可以列出仅进程的PIDs。

---
- hosts: localhost
  become: false
  gather_facts: false

  tasks:

  - name: 从链接获取详细信息
    ansible.builtin.command: ps -C {{ process }} -o pid=
    register: result
    changed_when: false

  - name: 将命令的结果转换为JSON
    ansible.builtin.debug:
      msg: "{{ result.stdout | community.general.jc('ps') }}"

请注意,community.general.jc有其自己的要求,需要在解决之前解决。此外,需要指定解析器。由于缺乏测试环境,我尚未测试pspgrep命令。

更多类似的文档和问题答案

英文:

> I need to extract PID and name from the above output.

Since you are already know the name of the process and since you are looking it up exclusively, the name is already know and you would need to extract the PIDs only.

For a more generic How to split the stdout_lines and convert it into a dictionary you could just go with the already given answer here.


An other approach could be to use the jc filter – Convert output of many shell commands and file-types to JSON maybe together with listing the PIDs of the process only.

---
- hosts: localhost
  become: false
  gather_facts: false

  tasks:

  - name: Get detailed information from links
    ansible.builtin.command: ps -C {{ process }} -o pid=
    register: result
    changed_when: false

  - name: Convert command&#39;s result to JSON
    ansible.builtin.debug:
      msg: &quot;{{ result.stdout | community.general.jc(&#39;ps&#39;) }}&quot;

<sub>... not fully tested yet</sub>

Please take note that community.general.jc has it's own requirements which needs to resolved before. Furthermore, it will be necessary to specifiy the Parser. Because of the lack of testing environment, I haven't tested for the ps or pgrep command yet.

Further Documentation Similar Q&A

答案3

得分: 0

尝试使用 pgrep -l run.sh

-l 仅列出进程ID和进程名称

您最终对字典的处理将有助于确定最佳行动方案。

英文:

Try using pgrep -l run.sh

-l lists only the pid and the process name

What you end up doing with the dictionary would help determine the best course of action.

huangapple
  • 本文由 发表于 2023年6月22日 18:19:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76530882.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定