I have a command in my ansible script that replaces a line in a file. The command works just fine when ran on my machine. However, when it's ran with my ansible script, it says No such file or directory
. The thing is, the file DOES exist and 'sed' DID replace that line. So the command did run successfully, but it's still gave me an error? Anyone know what might be causing this?
Ansible task
- name: Update path in plotly package
become: true
shell:
cmd:
sed -e '2s/.*/DIR="$( cd "$( \/usr\/bin\/dirname "${BASH_SOURCE[0]}" )" >\/dev\/null 2>\&1 \&\& pwd )"/' -i '' /plotly/app/venv/lib64/python3.9/site-packages/kaleido/executable/kaleido
Error
TASK [packages/plotly : Replace line in plotly package] ********************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "sed -e '2s/.*/DIR=\"$( cd \"$( \\/usr\\/bin\\/dirname \"${BASH_SOURCE[0]}\" )\" >\\/dev\\/null 2>\\&1 \\&\\& pwd )\"/' -i '' /plotly/app/venv/lib64/python3.9/site-packages/kaleido/executable/kaleido", "delta": "0:00:00.004789", "end": "2024-07-30 16:16:24.704142", "msg": "non-zero return code", "rc": 2, "start": "2024-07-30 16:16:24.699353", "stderr": "sed: can't read : No such file or directory", "stderr_lines": ["sed: can't read : No such file or directory"], "stdout": "", "stdout_lines": []}
For your Use Case it is recommended to use the lineinfile
module – Manage lines in text files instead, even ini_file
module – Tweak settings in INI files might be feasible. A specific Ansible module is usually less error prone, has better abstraction and error handling, supports check_mode
, diff
mode, changed
, has safe_file_operations
, can ensure idempotence, and many reasons more ...
Anyways, on a RHEL-system, for a test file like
- This
- is
- a
- test.
a less recommended minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- shell:
cmd: |
sed --in-place '/ is/{
s// was/g
w /dev/stdout
}' /home/ansible/test.txt
register: result
changed_when: result.stdout_lines | length | int > 0
- debug:
var: result
will result into an output of
TASK [shell] **********************************
changed: [localhost]
TASK [debug] **********************************
ok: [localhost] =>
result:
changed: true
cmd: |-
sed --in-place '/ is/{
s// was/g
w /dev/stdout
}' /home/ansible_user/test.txt
delta: '0:00:00.006268'
end: '2024-07-31 11:00:00.648871'
failed: false
msg: ''
rc: 0
start: '2024-07-31 11:00:00.642603'
stderr: ''
stderr_lines: []
stdout: '- was'
stdout_lines:
- '- was'
PLAY RECAP ***********************************
localhost : ok=2 changed=1
and a changed file of
- This
- was
- a
- test.
The second run would result into
TASK [shell] *********************************
ok: [localhost]
TASK [debug] *********************************
ok: [localhost] =>
result:
changed: false
...
PLAY RECAP ***********************************
localhost : ok=2 changed=0
Further Reading
As one probably also need to think about How to report sed --in-place
changes?, as well How to print line numbers changed by sed
?