2

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.

3 Answers 3

3

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]

Notes:

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

  • Example of a complete playbook for testing
- 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
Sign up to request clarification or add additional context in comments.

Comments

0

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's result to JSON
    ansible.builtin.debug:
      msg: "{{ result.stdout | community.general.jc('ps') }}"

... not fully tested yet

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

Comments

-1

Your output is essentially a list where each element is a string containing the PID, process name, and arguments.

Split and Process the Data:

  • Iterate over the list of stdout_lines.
  • Split each line of output into separate parts (PID, process name, and arguments).
  • Construct a dictionary with the PID as the key and the process name as the value.
- name: Get all running processes
  shell:
    cmd: pgrep -a run.sh
  register: _get_pid_and_name

- name: Create dictionary from PIDs and process names
  set_fact:
    process_dict: "{{ process_dict | default({}) | combine({item.split()[0]: item.split()[1]}) }}"
  loop: "{{ _get_pid_and_name.stdout_lines }}"

- name: Print the process dictionary
  debug:
    var: process_dict
  • Use the set_fact module to create a dictionary named process_dict.

  • The loop iterates through each line of the stdout_lines.

  • Inside the loop:

    • item.split()[0] extracts the PID (the first element after splitting the line).
    • item.split()[1] extracts the process name (the second element).
    • The combine filter efficiently merges the extracted PID (key) and process name (value) into the dictionary.

Example Output:

process_dict: {
  "1234223": "/bin/ksh",
  "4356223": "/bin/ksh",
  "887455": "/bin/ksh",
  # .... and so on
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.