I'm trying to unarchive a tar.gz file with ansible (which I've done quite a bit) but for some reason I can't get around this error this time.
I keep getting:
"msg": "Failed to find handler for \"/tmp/ansible_mnXJGp/internalbuildscripts1.tar.gz\". Make sure the required command to extract the file is installed. Command \"/bin/tar\" could not handle archive. Command \"/usr/bin/unzip\" could not handle archive."
what weird is that it seems to be trying to use unzip on a tar.gz file.
the task looks like this:
- name: Download build scripts
unarchive:
src: https://sblah.com/internalbuildscripts1.tar.gz
dest: /home/xxxx/buildscripts
remote_src: yes
So I had the same problem and ended up debugging the unarchive module to find out why it thought it couldn't handle the file.
TL;DR My dest was a relative path. The check that unarchive did to check if gtar would handle the file was this:
/usr/local/bin/gtar --list -C ./my/dest/path -z -f /Users/fransf/.ansible/tmp/ansible-tmp-1603283396.0748851-45418-232955281061540/source
but it did this with the working dir ALSO set to ./my/dest/path, so it was effectively trying to untar into ./my/dest/path/my/dest/path, which didn't exist!
So that was the problem in my case. I changed to using an absolute path and unarchive was happy. I do think this is a bug and apparently a test case that isn't in the unarchive test suite yet.
Debugging the Ansible module
Run your playbook with the ANSIBLE_KEEP_REMOTE_FILES environment variable set to 1 (i.e. ANSIBLE_KEEP_REMOTE_FILES=1 ansible-playbook -vvvv deploy.yml). Somewhere in the output (if you run with -vvvv) you'll see something like:
EXEC /bin/sh -c '/usr/local/Cellar/ansible/2.9.10/libexec/bin/python3.8 /Users/fransf/.ansible/tmp/ansible-tmp-1603283396.0748851-45418-232955281061540/AnsiballZ_unarchive.py && sleep 0'
Run that same command but with the explode parameter, like so:
/usr/local/Cellar/ansible/2.9.10/libexec/bin/python3.8 /Users/fransf/.ansible/tmp/ansible-tmp-1603283396.0748851-45418-232955281061540/AnsiballZ_unarchive.py explode
You'll get some output that tells you where the exploded module source was written to, e.g.
2955281061540/AnsiballZ_unarchive.py explode
Module expanded into:
/Users/fransf/.ansible/tmp/ansible-tmp-1603283396.0748851-45418232955281061540/debug_dir
Now you've got the Python source that you can either sprinkle with print statements or (this is what I did) run through an actual debugger. To run the module, use the same command as for exploding, but specify execute instead of explode:
/usr/local/Cellar/ansible/2.9.10/libexec/bin/python3.8 /Users/fransf/.ansible/tmp/ansible-tmp-1603283396.0748851-45418-232955281061540/AnsiballZ_unarchive.py execute
You can do this from the command line or from your IDE. I was already using IntelliJ Ultimate and installing the Python plugin was all I needed to be able to run this module through the debugger, set breakpoints, look at variables, and find out where it was messing up.
Hope this helps others with a similar problem.
I invite you to read #Frans answer first
I had almost the same problem:
Same error
The cause was that remote user is different from local one.
Workaround
Set ansible_remote_tmp to /tmp in the playbook
---
- name: "name of play"
hosts: all
become: true
vars:
# Setting this for unarchive to work
ansible_remote_tmp: /tmp
Related
We are using Ansible to deploy components and, in writing the jinja2 templates, it occurs to me that keeping my .config in sync with my .config.j2 is going to be something I need to "remember" going forward.
Are there better tools than "remembering" to keep the j2 in sync with the latest config files? I am open to all ideas... merge checks? Tests?
There are several things that you can do. Here are some of my ideas about how to do that.
Using a Makefile. With the help of that, instead of doing ansible-playbook -i BLAH BLAH BLAH playbok.yml, you just need to set few rules for that and with a simple command, something like make run-ansible all the steps from sync to apply ansible playbook works well for you.Take a look at this pseudo make file:
.PHONY : run-ansible run sync
sync:
cp .config.j2 .confg
run:
ansible-playbook -i host -u user playbook.yml
run-ansible: sync run
Use pre_tasks before running your role to update/sync .config file from .config.j2
Using conditional include. In case the .config is not updated, run another tasks which generate .config from .config.j2. Doing such a thing is so simple. This link could help you.
I am running the script module in a role on a windows machine.
I am attempting to use the "args: creates:" parameter. The script runs but the file that 'creates' is supposed to generate never gets created. When I run the playbook again the script runs a second time.
I've tried changing the file name and directory, I've tried using the environment variable to designate HOME as the root directory but the file never gets generated.
---
- name: run script
script: ./files/script.ps1 PARAMETERS
args:
creates: script_has_been_run.txt
Q: "The script runs but the file that 'creates' is supposed to generate never gets created."
A: It's the responsibility of the script to create the file. Quoting from script
creates: A filename on the remote node, when it already exists, this step will not be run.
The purpose of the parameter creates is to make the module idempotent, i.e run the script if the file does not exist. Once the file has been created, by the script, the task will be skipped.
I have written a playbook which download the tar file & extract it to some directory in Mac.But when I run the playbook it fails with below error
"msg": "Failed to find handler for \"/Users/harmeet/.ansible/tmp/ansible-tmp-1549339698.75-251687957122076/config.tar9IXAUQ.gz\". Make sure the required command to extract the file is installed. Command \"/usr/bin/tar\" detected as tar type bsd. GNU tar required. Command \"/usr/bin/unzip\" could not handle archive.
Code for playbook
-name: Download the tar for sample config
unarchive:
src: http://someremoteurl/config.tar.gz
dest: /Users/{{ansible_user}}/.myfolder/
remote_src: yes
creates: /Users/{{ansible_user}}/.myfolder/config
If use a zip fie on remote Server such as http://someremoteurl/config.zip then this task works but for tar files it fails .
I have also installed gnu tar such as gtar & updated path in .bash_src after reviewing this question
Actually on macOS it looks for GNU based tar archive module which was not found on mac. So if you use zip module for mac in ansible it will work but for that we may need to change the playbook file & it can create issues as i am using single playbook for both mac and linux. I used GNU based tar archive module to solve this issue.
I solved this issue by below steps
Install gtar by homebrew. brew install gnu-tar
Set path of gtar in .bashsrc file otherwise it will not able to use gtar for unarchive. Usually .bashsrc exist at $HOME path. if not exist then create it.
export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
export MANPATH="/usr/local/opt/gnu-tar/libexec/gnuman:$MANPATH"
Thanks
If your default shell is zsh, then you should put the following in ~/.zshenv:
export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
You can check if it's working correctly by:
ansible the-hostname -m command -a "which tar"
I am investigating an issue with ansible and suspect whether a registered variable was saved in ansible tmp folder, because I also suspect that such temporary directory is being removed by async_wrapper module during execution (the environment is based on ansible 2.2 and there is a known issue with async_wrapper module).
Therefore I would like to know what kind of items are expected to be saved in ansible tmp folder such as in .ansible/tmp/ansible-tmp-xxx... during execution of a task. Then at least it would be possible to make some further estimations.
Use:
export ANSIBLE_KEEP_REMOTE_FILES=1
This will retain the files that Ansible copies to .ansible/tmp/ansible-tmp-xxx... and runs on the destination host.
Set the env variable before running the playbook with -vvv. This will output the paths used to store the scripts on the destination host.
After the playbook has completed. SSH onto the destination host and take a look at the files.
The files are most likely on a path like:
/home/user/.ansible/tmp/..../modulename
The easiest way to view/test them is to explode them and then execute them.
python /home/user/.ansible/tmp/..../modulename explode
This will create a subdirectory containing the module, arguments and ansible wrapper.
python /home/user/.ansible/tmp/..../modulename execute
This will run the exploded files.
You will be able to see from this exactly what is being saved where. It's also possible to edit the module and test to see what changes are made to the /tmp folder.
Currently, I'm using shell script to download the files from FTP server. Ansible will execute my script and continue other automated jobs.
Please let me know the best way to do this in Ansible playbook using "get_url" instead of "shell". The following syntax is working only to download the single file but my requirements are to download the multiple files and directories.
Appreciated your help.
- name: FTP Download
get_url: url=ftp://username:password#ftp.server.com/2016/03/value/myfile dest=/home/user/03/myfile1
register: get_url_result
According to the get_url documentation, and as far as I know, get_url does not support recursive download.
One possibility, as #helloV suggested, is to loop through a list with with_items. But this would require to have a static list of files or to obtain this list somehow, probably with wget.
Consequently, you could simply use wget -m directly in order to recursively download all files with one task. See How to recursively download a folder via FTP on Linux.
Use a list for urls (or a dict for urls and dest) and then loop through it using with_items.
Give an example for few URLs and destination files.