If you are not familiar with modules, check out Ansible - Getting Started with Modules.
The unarchive module is used to extract an archive, such as a .zip file or a tar archive. By default, unarchive will extract the archive on your control node (that's your Ansible server) to a directory on the managed node (e.g. target system).
The remote_src parameter can be used to extract an archive on the managed node to a directory on the managed node.
AVOID TROUBLE
If you attempt to extract an archive that contains no files (an empty archive), the following fatal error will be returned.
fatal: [server1.example.com]: FAILED! => {
"changed": false,
"msg": "Failed to find handler for \\"foo.tar.gz\\". Make sure the required command to extract the file is installed. Command \\"/bin/gtar\\" found no files in archive. Command \\"/bin/gtar\\" could not handle archive. Command \\"/bin/unzip\\" could not handle archive."
}
To account for this situation, you may want to use the shell module to first determine if the archive is empty. Then, you can apply when: out.stdout != '' to the unarchive task.
- name: check to see if the archive is empty
shell: "tar -ztf foo.tar.gz"
register: out
failed_when: out.rc not in [ 0, 1 ]
warn: false
In this example, foo.zip on the control node will be extracted to the /tmp directory on the managed node. The list_files and register parameters are not required, but can be helpful in debugging.
- name: extract /path/to/foo.zip
unarchive:
src: /path/to/foo.zip
dest: /tmp
list_files: true
register: out
If the destination directory does not exist on the managed node, something like this will be displayed. For this reason, you may want to use the file module to create the dest directory before using the unarchive module.
TASK [unarchive]
fatal: [server1.example.com]: FAILED! => {"changed": false, "msg": "dest '/tmp/bogus' must be an existing dir"}
On the other hand, if the file is successfully unarchived, something like this should be displayed.
TASK [unarchive]
changed: [server1.example.com]
unzip
When attempting to unarchive a .zip file, the unzip package must exists on the managed node. If the unzip package is not installed on the managed node, something like this should be displayed. For this reason, you may want to use the yum module to install the unzip package on the managed node before using the unarchive module.
TASK [unarchive]
fatal: [server1.example.com]: FAILED! => {"changed": false, "msg": "Failed to find handler for \"/root/.ansible/tmp/ansible-tmp-1609665721.5095057-23328-132110161264122/source\". Make sure the required command to extract the file is installed. Command \"unzip\" not found. Command \"/usr/bin/gtar\" could not handle archive."}
extract a single file
Let's say example.tar.gz contains numerous files, but you only want to extract a single file from the archive. The --add-file extra option can be used. In this example, only usr/local/foo.txt will be extracted.
- name: extract only foo.txt from foo.zip
unarchive:
src: /path/to/foo.zip
dest: /
extra_opts:
- "--add-file"
- "usr/local/foo.txt"
register: out
roles
If using the unarchive module in a role (see Ansible - Getting Started with Roles), the file being unarchived can be placed in the roles files directory.
roles/foo/files/foo.zip
Then, src would just be the name of the file that is being unarchived.
- name: extract foo.zip to /tmp
unarchive:
src: foo.zip
dest: /tmp
remote_src: yes can be used to extract an archive on the managed node to a directory on the managed node. In this example, foo.zip on the managed node will be extracted to the /tmp directory on the managed node.
- name: extract /path/to/foo.zip
unarchive:
src: /path/to/foo.zip
dest: /tmp
remote_src: yes
The register parameter can be used to store the result of the unarchive in a variable. In this example, the results will be stored in the 'out' variable.
- name: extract /path/to/foo.zip
unarchive:
src: /path/to/foo.zip
dest: /tmp
register: out
The debug module can be used to print the 'out' variable.
- name: "print the 'out' variable"
debug:
var: out
Something like this should be returned. When "changed" is "false", this means the file was not extracted.
ok: [server1.example.com] => {
"msg": {
"changed": false,
"dest": "/tmp",
"failed": false,
"gid": 0,
"group": "root",
"handler": "ZipArchive",
"mode": "01777",
"owner": "root",
"secontext": "system_u:object_r:tmp_t:s0",
"size": 8192,
"src": "/tmp/foo.zip",
"state": "directory",
"uid": 0
}
}
When "changed" is "true", this means the file was extracted.
changed: [server1.example.com] => {
"msg": {
"changed": true,
"dest": "/tmp",
"diff": {
}
"extract_results": {
"cmd": [
"/bin/unzip",
"-o",
"/tmp/foo.zip",
"-d",
"/tmp"
],
"err": "",
"out": "Archive: /tmp/foo.zip\n inflating: /tmp/path/to/foo.txt \n inflating: /tmp/path/to/bar.txt
}
"failed": false,
"gid": 0,
"group": "root",
"handler": "ZipArchive",
"mode": "01777",
"owner": "root",
"secontext": "system_u:object_r:tmp_t:s0",
"size": 8192,
"src": "/tmp/foo.zip",
"state": "directory",
"uid": 0
}
}