Getting past "non-zero return code"

239 views
Skip to first unread message

Dimitri Yioulos

unread,
Mar 21, 2024, 10:00:35 AM3/21/24
to Ansible Project
Good day.

I want tp parse root's history to return the last occurrence of yum update that includes the string "disablerepo". I would have thought that this would work:

---

- hosts: all
  gather_facts: false
  become: yes

  tasks:

    - name: Get last yum update which includes "disablerepo"
      shell: 'history | grep -m 1 disablerepo'
      register: out


but, I get this error:

fatal: [myhost1]: FAILED! => changed=true
  ansible_facts:
    discovered_interpreter_python: /usr/bin/python3
  cmd: history | grep -m 1 disablerepo
  delta: '0:00:00.013135'
  end: '2024-03-21 09:54:12.391498'
  msg: non-zero return code
  rc: 1
  start: '2024-03-21 09:54:12.378363'
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>


The command "history | grep -m 1 disablerepo" works fine at the command line. I've tried every manner of escaping characters and changing the command itself, but get errors regardless. How can I get the desired results?

Brian Coca

unread,
Mar 21, 2024, 10:52:09 AM3/21/24
to ansible...@googlegroups.com
You can control the failure handling from the task using
'failed_when', for example:

failed_when: out is failed and not out.rc == 1



--
----------
Brian Coca (he/him/yo)

Dimitri Yioulos

unread,
Mar 21, 2024, 11:11:37 AM3/21/24
to Ansible Project
Thank you, Brian. Now, I want to print that output via debug, but am again running into "non-zero return code".

Brian Coca

unread,
Mar 21, 2024, 12:01:58 PM3/21/24
to ansible...@googlegroups.com
when asking for help it is useful to show the full task and -vvv
output that includes the error (like your first post). It is hard to
debug from just a partial message out of context.

Dimitri Yioulos

unread,
Mar 21, 2024, 1:01:14 PM3/21/24
to Ansible Project
Apologies.

The playbook:

---

- hosts: all
  gather_facts: false
  become: yes
  become_user: root


  tasks:

    - name: Get last yum update which includes "disablerepo"
      shell: 'history | grep -m 1 disablerepo'
      failed_when: out is failed and not out.rc == 1
      register: out

    - debug: msg={{ out }}


The errors:

https://pastebin.com/q8qAB6Nw

Brian Coca

unread,
Mar 21, 2024, 1:16:01 PM3/21/24
to ansible...@googlegroups.com
he, you'll need the same condition for debug (or use a block) since
debug the way you set it up returns `rc: 1` and fools it into thinking
there is an error.
You can also bypass the top level rc with msg={{ 'out: ' ~ out }}

Dimitri Yioulos

unread,
Mar 21, 2024, 2:01:28 PM3/21/24
to Ansible Project
Playbook:

---

- hosts: all
  gather_facts: false
  become: yes
  become_user: root
  become_method: sudo


  tasks:

    - name: Get last yum update which includes "disablerepo"
      shell: 'history | grep -m 1 disablerepo'
      failed_when: out is failed and not out.rc == 1
      register: out

    - debug: msg={{ 'out' ~ out }}

Output:

ansible-playbook [core 2.15.6]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/deploy/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
  ansible collection location = /home/deploy/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.9.18 (main, Jan  4 2024, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] (/bin/python3)
  jinja version = 3.1.2
  libyaml = True
Using /etc/ansible/ansible.cfg as config file
redirecting (type: inventory) ansible.builtin.vmware_vm_inventory to community.vmware.vmware_vm_inventory
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
Parsed /etc/ansible/hosts inventory source with ini plugin
redirecting (type: callback) ansible.builtin.yaml to community.general.yaml
redirecting (type: callback) ansible.builtin.yaml to community.general.yaml
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: patchinfo.yml *******************************************************************************************************************
1 plays in patchinfo.yml

PLAY [all] ********************************************************************************************************************************

TASK [Get last yum update which includes "disablerepo"] ***********************************************************************************
task path: /etc/ansible/playbooks/patchinfo.yml:11
Thursday 21 March 2024  13:27:29 -0400 (0:00:00.017)       0:00:00.017 ********
Thursday 21 March 2024  13:27:29 -0400 (0:00:00.017)       0:00:00.017 ********
<myhost> ESTABLISH SSH CONNECTION FOR USER: None
< myhost  > SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"'  myhost   '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
< myhost  > (0, b'/home/deploy\n', b'')
< myhost  > ESTABLISH SSH CONNECTION FOR USER: None
< myhost  > SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"'  myhost   '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /home/deploy/.ansible/tmp `"&& mkdir "` echo /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887 `" && echo ansible-tmp-1711042050.3964171-1907771-209611470269887="` echo /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887 `" ) && sleep 0'"'"''
< myhost  > (0, b'ansible-tmp-1711042050.3964171-1907771-209611470269887=/home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887\n', b'')
< myhost  > Attempting python interpreter discovery
< myhost  > ESTABLISH SSH CONNECTION FOR USER: None
< myhost  > SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"'  myhost   '/bin/sh -c '"'"'echo PLATFORM; uname; echo FOUND; command -v '"'"'"'"'"'"'"'"'python3.11'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.10'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.9'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.8'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.6'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.5'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/bin/python3'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/libexec/platform-python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python2.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/bin/python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python'"'"'"'"'"'"'"'"'; echo ENDFOUND && sleep 0'"'"''
< myhost  > (0, b'PLATFORM\nLinux\nFOUND\n/usr/bin/python3.9\n/usr/bin/python3\n/usr/libexec/platform-python\n/usr/bin/python\n/usr/bin/python\nENDFOUND\n', b'')
< myhost  > ESTABLISH SSH CONNECTION FOR USER: None
< myhost  > SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"'  myhost   '/bin/sh -c '"'"'/usr/bin/python3.9 && sleep 0'"'"''
< myhost  > (0, b'{"platform_dist_result": [], "osrelease_content": "NAME=\\"Red Hat Enterprise Linux\\"\\nVERSION=\\"9.3 (Plow)\\"\\nID=\\"rhel\\"\\nID_LIKE=\\"fedora\\"\\nVERSION_ID=\\"9.3\\"\\nPLATFORM_ID=\\"platform:el9\\"\\nPRETTY_NAME=\\"Red Hat Enterprise Linux 9.3 (Plow)\\"\\nANSI_COLOR=\\"0;31\\"\\nLOGO=\\"fedora-logo-icon\\"\\nCPE_NAME=\\"cpe:/o:redhat:enterprise_linux:9::baseos\\"\\nHOME_URL=\\"https://www.redhat.com/\\"\\nDOCUMENTATION_URL=\\"https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9\\"\\nBUG_REPORT_URL=\\"https://bugzilla.redhat.com/\\"\\n\\nREDHAT_BUGZILLA_PRODUCT=\\"Red Hat Enterprise Linux 9\\"\\nREDHAT_BUGZILLA_PRODUCT_VERSION=9.3\\nREDHAT_SUPPORT_PRODUCT=\\"Red Hat Enterprise Linux\\"\\nREDHAT_SUPPORT_PRODUCT_VERSION=\\"9.3\\"\\n"}\n', b'')
Using module file /usr/local/lib/python3.9/site-packages/ansible/modules/command.py
< myhost  > PUT /home/deploy/.ansible/tmp/ansible-local-1907766dv65hq7i/tmpywer5c4x TO /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887/AnsiballZ_command.py
< myhost  > SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"' '[ myhost  ]'
< myhost  > (0, b'sftp> put /home/deploy/.ansible/tmp/ansible-local-1907766dv65hq7i/tmpywer5c4x /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887/AnsiballZ_command.py\n', b'')
< myhost  > ESTABLISH SSH CONNECTION FOR USER: None
< myhost  > SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"'  myhost   '/bin/sh -c '"'"'chmod u+x /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887/ /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887/AnsiballZ_command.py && sleep 0'"'"''
< myhost  > (0, b'', b'')
< myhost  > ESTABLISH SSH CONNECTION FOR USER: None
< myhost  > SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"' -tt  myhost   '/bin/sh -c '"'"'sudo -H -S -n  -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-tbpakhcbvetvnsybvzpszpsloqswokel ; /usr/bin/python3 /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887/AnsiballZ_command.py'"'"'"'"'"'"'"'"' && sleep 0'"'"''
Escalation succeeded
< myhost  > (1, b'\r\n{"changed": true, "stdout": "", "stderr": "", "rc": 1, "cmd": "history | grep -m 1 disablerepo", "start": "2024-03-21 13:27:31.520120", "end": "2024-03-21 13:27:31.533996", "delta": "0:00:00.013876", "failed": true, "msg": "non-zero return code", "invocation": {"module_args": {"_raw_params": "history | grep -m 1 disablerepo", "_uses_shell": true, "stdin_add_newline": true, "strip_empty_ends": true, "argv": null, "chdir": null, "executable": null, "creates": null, "removes": null, "stdin": null}}}\r\n', b'Shared connection to  myhost   closed.\r\n')
< myhost  > Failed to connect to the host via ssh: Shared connection to  myhost   closed.
< myhost  > ESTABLISH SSH CONNECTION FOR USER: None
< myhost  > SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/home/deploy/.ansible/cp/7caa706ba6"'  myhost   '/bin/sh -c '"'"'rm -f -r /home/deploy/.ansible/tmp/ansible-tmp-1711042050.3964171-1907771-209611470269887/ > /dev/null 2>&1 && sleep 0'"'"''
< myhost  > (0, b'', b'')
changed: [ myhost ] => changed=true
  ansible_facts:
    discovered_interpreter_python: /usr/bin/python3
  cmd: history | grep -m 1 disablerepo
  delta: '0:00:00.013876'
  end: '2024-03-21 13:27:31.533996'
  failed_when_result: false
  invocation:
    module_args:
      _raw_params: history | grep -m 1 disablerepo
      _uses_shell: true
      argv: null
      chdir: null
      creates: null
      executable: null
      removes: null
      stdin: null
      stdin_add_newline: true
      strip_empty_ends: true

  msg: non-zero return code
  rc: 1
  start: '2024-03-21 13:27:31.520120'

  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>

TASK [debug] ******************************************************************************************************************************
task path: /etc/ansible/playbooks/patchinfo.yml:16
Thursday 21 March 2024  13:27:31 -0400 (0:00:02.060)       0:00:02.078 ********
Thursday 21 March 2024  13:27:31 -0400 (0:00:02.060)       0:00:02.077 ********
ok: [ myhost ] =>
  msg: 'out{''changed'': True, ''stdout'': '''', ''stderr'': '''', ''rc'': 1, ''cmd'': ''history | grep -m 1 disablerepo'', ''start'': ''2024-03-21 13:27:31.520120'', ''end'': ''2024-03-21 13:27:31.533996'', ''delta'': ''0:00:00.013876'', ''failed'': False, ''msg'': ''non-zero return code'', ''stdout_lines'': [], ''stderr_lines'': [], ''ansible_facts'': {''discovered_interpreter_python'': ''/usr/bin/python3''}, ''failed_when_result'': False}'

Dimitri Yioulos

unread,
Mar 21, 2024, 2:08:35 PM3/21/24
to Ansible Project
I should have mentioned that this is the expected output, for example:

[dyioulos@myhost ~]$ history | grep -m 1 disablerepo
   87  dnf install --disablerepo=somerepo https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm

Todd Lewis

unread,
Mar 21, 2024, 2:28:54 PM3/21/24
to ansible...@googlegroups.com, uto...@gmail.com
Your problem isn't anything to do with Ansible. It's a problem is an interaction between how history is implemented and privilege escalation via become.

To make your task work, you'll need to change your shell script like this:
    - name: Get last yum update which includes "disablerepo"
      shell: |
         HISTFILE=/root/.bash_history
         history -n
         history | tac | grep -m 1 disablerepo
      register: out
Normally, HISTFILE isn't set. The docs say it defaults to "~/.bash_history", and it sort of does – for a broad enough definition of who "~" references. Anyway, in my testing, it's necessary to explicitly set it as shown above.

Simply pointing HISTFILE at the right file isn't enough. The shell normally reads in the HISTFILE early on, but we're well past that by line 2 of the shell script. The "history -n" command reads "all history lines not already read from the history file and append[s] them to the history list". The "history list" is not the same as the history file; it's an in-memory construct that the shell manipulates until you close the shell. It's then that the history list is written to the file. (Or when you invoke "history -a" or "history -w".)

Now that you've got the history loaded, you can do your grep. The failure that was being reported before was the result of trying to construct the pipe between an uninitialized history list and your grep. A bare history command at that spot just does nothing, but as part of a pipeline it would fail.

However, you stated you want the last yum update which includes "disablerepo". What you would have gotten - had it not been for the failure to build a pipeline with an uninitialized history - was the first command in the history which included "disablerepo". Inserting tac in the pipeline reverses the order so your grep will match on the last occurrence.

Cheers,
--
Todd
--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/1d4dfd6c-913a-4360-a204-5a1ad6644109n%40googlegroups.com.

-- 
Todd
Message has been deleted

Dimitri Yioulos

unread,
Mar 21, 2024, 2:52:06 PM3/21/24
to Ansible Project
Thank you, Todd! This works:


---

- hosts: all
  gather_facts: false
  become: yes
  
  tasks:

    - name: Get last yum update which includes "disablerepo"
      shell: |
         HISTFILE=/root/.bash_history
         history -n
         history | tac | grep -m 1 disablerepo
      register: out

    - debug: msg={{ out.stdout }}
Reply all
Reply to author
Forward
0 new messages