My requirement is to use grep -E
option in Ansible.
I wish to first use /usr/xpg4/bin/grep
if it is present on the server else switch to /bin/grep
I'm looking for a POSIX solutions that works on various shells and operating systems.
Below command works fine on command-line:
$ ls /usr/xpg4/bin/grep 2> >(grep -v 'No such file or directory' >&2) || ls /bin/grep 2> >(grep -v 'No
> such file or directory' >&2)
Output:
/usr/xpg4/bin/grep
I tried using the above solution in Ansible like below:
- name: "Detect the grep on the system"
ignore_errors: yes
command: "ls /usr/xpg4/bin/grep 2> >(grep -v 'No such file or directory' >&2) || ls /bin/grep 2> >(grep -v 'No such file or directory' >&2 | head -1"
register: grepfound
In the output it finds both the grep and instead of getting one single preferred /usr/xpg4/bin/grep
{{ grepfound.stdout }}
prints both the grep which I never wanted.
Output:
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["ls", "/usr/xpg4/bin/grep", "2>", ">(grep", "-v", "No such file or directory", ">&2)", "||", "ls", "/bin/grep", "2>", ">(grep", "-v", "No such file or directory", ">&2"], "delta": "0:00:00.013219", "end": "2021-06-14 05:25:52.178385", "msg": "non-zero return code", "rc": 2, "start": "2021-06-14 05:25:52.165166", "stderr": "2>: No such file or directory\n>(grep: No such file or directory\n-v: No such file or directory\nNo such file or directory: No such file or directory\n>&2): No such file or directory\n||: No such file or directory\nls: No such file or directory\n2>: No such file or directory\n>(grep: No such file or directory\n-v: No such file or directory\nNo such file or directory: No such file or directory\n>&2: No such file or directory", "stderr_lines": ["2>: No such file or directory", ">(grep: No such file or directory", "-v: No such file or directory", "No such file or directory: No such file or directory", ">&2): No such file or directory", "||: No such file or directory", "ls: No such file or directory", "2>: No such file or directory", ">(grep: No such file or directory", "-v: No such file or directory", "No such file or directory: No such file or directory", ">&2: No such file or directory"], **"stdout": "/bin/grep\n/usr/xpg4/bin/grep"**, "stdout_lines": ["/bin/grep", "/usr/xpg4/bin/grep"]}
...ignoring
I tried using {{ grepfound.stdout_lines[0] }}
as a workaround but as you see it prints /bin/grep
instead of /usr/xpg4/bin/grep
. And if i use {{ grepfound.stdout_lines[1] }}
it will work here but fail where only one grep is found.
I would have still liked your help use stdout_lines instead of stdout so that the processes show up better formatted segregated... each process in a new-line
That is where | select
comes into play -- it is designed to filter items of a list where the jinja2 test evaluates to true
- set_fact:
example_data:
stdout_lines:
- 1111 nothing here
- 2222 this one is httpd
- 3333 this one is tomcat
- 4444 again nothing
- debug:
msg: |
the things as a list are:
{{ example_data.stdout_lines | select('search', '(tomcat|weblogic|httpd)') | list }}
but you can also fold them back into one str:
{{ example_data.stdout_lines | select('search', '(tomcat|weblogic|httpd)') | join(nl) }}
vars:
# this silliness is to work around a quirk of jinja2 where
# | join("\n") literally uses `"\n"` to join items :-(
nl: "\n"
produces
msg: |-
the things as a list are:
['2222 this one is httpd', '3333 this one is tomcat']
but you can also fold them back into one str:
2222 this one is httpd
3333 this one is tomcat