Reputation: 1098
I'm having issues to get my command output when task timeout is reached.
Here is my task:
- name: test of echo-ing something
ansible.builtin.command:
cmd: "/bin/echo 'it works !'"
timeout: 10
register: command_result
ignore_errors: yes
- name: command_result
ansible.builtin.debug:
var: command_result
When there is no timeout, everything goes well, I have in command_result variable:
ok: [server1] => {
"command_result": {
"changed": true,
"cmd": [
"/bin/echo",
"it works !"
],
"delta": "0:00:00.004629",
"end": "2022-03-24 09:47:12.104234",
"failed": false,
"msg": "",
"rc": 0,
"start": "2022-03-24 09:47:12.099605",
"stderr": "",
"stderr_lines": [],
"stdout": "it works !",
"stdout_lines": [
"it works !"
]
}
}
However, when I make my command triggering the timeout (for example: cmd: "/bin/sleep 40"
), I have this :
TASK [test of echo-ing something] ***************************************
fatal: [server1]: FAILED! => {"changed": false, "msg": "The ansible.builtin.command action failed to execute in the expected time frame (10) and was terminated"}
...ignoring
TASK [command_result] ***************************************************
ok: [server1] => {
"command_result": {
"changed": false,
"failed": true,
"msg": "The ansible.builtin.command action failed to execute in the expected time frame (10) and was terminated"
}
}
How to get standard output (stdout) and/or standard error (stderr) from the command when timeout is reached ? On my CI/CD, I need it to know why a command had reached the timeout
Thanks !
[EDIT] Regarding the answer given by @vladimir-botka I found another way to timeout command and not tasks. I'm pasting it here just in case it helps other people:
- name: "exec my command"
ansible.builtin.shell:
cmd: "timeout -v --foreground --signal=SIGINT 600 my_script.sh"
chdir: "{{ work_dir }}"
executable: /bin/bash
register: cmd_output
- name: "command output"
ansible.builtin.debug:
var: cmd_output
Upvotes: 3
Views: 4023
Reputation: 1
The best solution is already here, but for the sake of completeness I'll add another possibility.
There is also a possible workaround to redirect the command output to a temporary file and then print the file contents.
Example:
- name: Create a temporary file to store script.sh output
command: mktemp
register: output_file
- name: Run script.sh
shell: >
script.sh
param1
param2 > {{ output_file.stdout }}
async: 120
poll: 60
ignore_errors: yes
- slurp:
src: "{{ output_file.stdout }}"
register: script_stdout
- name: Print the script.sh output
debug:
msg: "{{ script_stdout.content | b64decode }}"
- file:
path: "{{ output_file.stdout }}"
state: absent
Upvotes: 0
Reputation: 68144
Q: "How to get stdout and/or stderr from the command when timeout is reached ?"
A: When a timeout is reached the task will be terminated not the command. Task keyword timeout says:
Time limit for task to execute in, if exceeded Ansible will interrupt and fail the task.
As a result, you don't get stdout/stderr from the command when the task's timeout is reached.
Note
One might expect to get stdout/stderr from the terminated command. For example, the script
shell> cat sleep_10.sh
#!/bin/bash
echo PID $$
sleep 10
echo Finished
exit 0
Will print Terminated
when killed by shell> kill SIGTERM 875125
shell> ./sleep_10.sh
PID 875125
Terminated
But when the script is executed by the Ansible module command
- command: '$PWD/sleep_10.sh'
timeout: 5
register: result
ignore_errors: true
- debug:
var: result
there is no stdout/stderr about the termination. Instead, the message says the task was terminated
result:
changed: false
failed: true
msg: The command action failed to execute in the expected time frame (5) and was terminated
Running the script asynchronously doesn't help either
- name: Run an async task
command: '$PWD/sleep_10.sh'
async: 5
poll: 0
register: result
- name: Check on an async task
async_status:
jid: "{{ result.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 10
delay: 2
ignore_errors: true
- debug:
var: job_result
gives (abridged)
TASK [Run an async task] *******************************************
changed: [localhost]
TASK [Check on an async task] **************************************
FAILED - RETRYING: [localhost]: Check on an async task (10 retries left).
FAILED - RETRYING: [localhost]: Check on an async task (9 retries left).
FAILED - RETRYING: [localhost]: Check on an async task (8 retries left).
FAILED - RETRYING: [localhost]: Check on an async task (7 retries left).
FAILED - RETRYING: [localhost]: Check on an async task (6 retries left).
fatal: [localhost]: FAILED! => changed=false
ansible_job_id: '633379103837.876333'
attempts: 6
child_pid: 876338
finished: 1
msg: Timeout exceeded
results_file: /home/admin/.ansible_async/633379103837.876333
started: 1
stderr: ''
stderr_lines: <omitted>
stdout: ''
stdout_lines: <omitted>
...ignoring
TASK [debug] ****************************************************
ok: [localhost] =>
job_result:
ansible_job_id: '633379103837.876333'
attempts: 6
changed: false
child_pid: 876338
failed: true
finished: 1
msg: Timeout exceeded
results_file: /home/admin/.ansible_async/633379103837.876333
started: 1
stderr: ''
stderr_lines: []
stdout: ''
stdout_lines: []
Upvotes: 4