In this post, we’re going to learn about the Ansible copy module.
Before we look at the copy module specifically, let us first remind ourselves what Ansible is. You can install this open-source software on just one Linux machine. Then it can perform a lot of tasks on connected Linux machines without requiring Ansible installation on them. You can do tasks like copying files, fetching files, and a lot of other things all on connected machines, with a single command.
For performing these tasks, Ansible uses modules like the copy module, Fetch module, get_url module, and others. Let’s now do a deep dive into the copy module, which we’ll use to perform different copy tasks.
Enhance visibility and governance of the artifact lifecycle
Learn how with KosliHow Does Copy Work in Ansible?
The copy module can be used to copy files easily from Ansible-controlled machines to remote machines. It can also copy within the same Ansible-controlled machine. In addition, it can be used to copy between two remote machines.
Ansible tasks are written in playbooks, which are YAML files. As mentioned earlier, Ansible needs to be installed only on one host and can be used to send files to any number of connected hosts, with a single command.
Below is a syntax of a simple file_copy.yml file. It is used to copy a file from the work folder called logs.txt to logs_cpy.txt in the same folder.
# file_copy.yml
- name: copy a file
hosts: localhost
connection: local
tasks:
- name: copy logs.txt as logs_copy.txt in the same folder
copy:
src: work/logs.txt
dest: work/logs_cpy.txt
tags:
- copy_easy
Also, note that if logs_cpy.txt exists in the work folder, then it will be overwritten in this case. Another important thing to note is the file_copy.yml file and work folder should be in the same directory. Just give the below command from the terminal to execute the tasks in the file_copy.yml file:
ansible-playbook file_copy.yml – tags "copy_easy" -v
How Do You Copy Files in Ansible?
Now we’ll look into the various ways in which we can copy files and directories in Ansible. In the previous section, we already saw how to copy the file locally. Now we’ll see other ways, starting with remote copying.
Copy File From Local to Remote
When you’re copying from local to remote, the remote system doesn’t need to have Ansible installed. We only need it to be mentioned in a file called hosts locally. Below is the YAML file for this.
Here, in hosts, we have mentioned serversremote, which is a group containing the list of remote hosts. In the tasks, become means that remote servers copy the file as the root user. The src and dest are self-explanatory in copy.
The owner, group, and mode will be set in the remote machine once the file is copied.
# file_copy.yml
- name: Copy file from Local to Remote
hosts: serversremote
tasks:
- name: copying a file
become: true
copy:
src: ~/work/logs.txt
dest: /Users/naben/work
owner: naben
group: staff
mode: 0644
tags:
- copy_remote
Just give the below command from the terminal to execute the tasks in the file_copy.yml file:
ansible-playbook file_copy.yml – tags "copy_remote" -v
Copy the File to a Directory That Doesn’t Exist
If we give a directory that doesn’t yet exist in the destination, then Ansible will create the directory. It will also make the destination file name the same as the source file name. Below is the YAML file for this.
Here, we have a file named data.txt inside a logs folder. We want to create a folder called dir_null inside it.
# file_copy.yml
- name: copy to destination
hosts: localhost
connection: local
tasks:
- name: copy data.txt to a directory, which doesn't exists
copy:
src: logs/data.txt
dest: logs/dir_null/
tags:
- dir_is_null
Just give the below command from the terminal to execute the tasks in the file_copy.yml file**:**
ansible-playbook file_copy.yml – tags "dir_is_null" -v
Now, when this command is run, it will create a new directory dir_null inside the logs directory. And the file will be named data.txt.
Copy the Entire Directory Recursively
If we want to copy a directory, along with its structure, then we should use the copy command as shown in the below YAML file. It will copy all the directories, along with their files, in a recursive manner. The destination will contain the replica of the whole directory.
In the below YAML file, we have given logs in src. Now, the logs folder contains the inner_logs and outer_logs folders. Each of them contains 10 log files.
# file_copy.yml
- name: copy entire directory
hosts: localhost
connection: local
tasks:
- name: copy logs directory to /temp
copy:
src: logs
dest: /temp/
directory_mode:
tags:
- dir_recursive
Just give the below command from the terminal to execute the tasks in the file_copy.yml file:
ansible-playbook file_copy.yml – tags "dir_recursive" -v
This command will copy the directory logs, which includes the inner_logs and outer_logs folders and their files, to the /temp directory.
Copy the Entire Directory Recursively, Without the Structure
If we want all the content of a directory except its structure, we should use the below YAML file. It will copy only the files from the inner directories.
In the below YAML file, we have given logs in src. Now, the logs folder contains the inner_logs and outer_logs folders. Each of them contains 10 log files. Here, one thing to notice is that we have a forward slash (/) in the src: logs/. This is the main thing we use to only copy content.
# file_copy.yml
- name: copy entire directory content
hosts: localhost
connection: local
tasks:
- name: copy logs directory content to /temp
copy:
src: logs/
dest: /temp/
directory_mode:
tags:
- dir_recursive_content
Just give the below command from the terminal to execute the tasks in the file_copy.yml file:
**ansible-playbook file_copy.yml – tags "dir_recursive_content" -v**
This command will copy the directory logs content, which are the files, to the /temp directory.
Copy Raw Multiline Content to the File
We can also copy raw content to a destination file using the Ansible copy module. Here, the src will be replaced by content in the YAML file. Also, notice that we can pass some predefined variables in the YAML file.
In our example, we’re passing a simple dictionary containing two key-value pairs. We’re then referring to these pairs in the content using double curly brackets: {{}}.
#file_copy.yml
- name: copy content to destination
hosts: localhost
connection: local
vars:
persondict:
name: John
age: 40
tasks:
- name: copy content to logs_dest.txt
copy:
content: |
Lorem ipsum dolor sit amet.
consectetur adipiscing elit.
Sed viverra egestas rhoncus,
{{ persondict }}
dest: logs/logs_dest.txt
tags:
- text_content
Just give the below command from the terminal to execute the tasks in the file_copy.yml file:
ansible-playbook file_copy.yml – tags "text_content" -v
This command will copy the content to the file logs_dest.txt in the logs folder. We can also check this in the terminal using the cat command.
nabendubiswas@Nabendus-Mac-mini ~ $ cat logs/logs_dest.txt
Lorem ipsum dolor sit amet.
consectetur adipiscing elit.
Sed viverra egestas rhoncus,
{'name': 'John', 'age': '40'}
Conclusion
In this post, we’ve learned about Ansible, as well as Ansible’s copy module. To copy the files and directories on a local machine, we use this module.
Besides this, you can use the copy module to copy files and directories from local machines to remote machines. The local machine is the only one that needs to have Ansible installed. Then the local host file should contain the details about remote machines.
We then learned five different ways to use the copy module to copy files. This included anything from simple copies to copying whole directories recursively. Also, we learned to copy from a local to a remote destination.
Ansible is good for automation, but sometimes when we push new changes to production, it breaks everything. It’s then really hard to debug whatever broke the complete system. Kosli tracks every change in production and gives us the root cause of the outage in seconds. Give it a try here.
This post was written by Nabendu Biswas. Nabendu has been working in the software industry for the past 15 years, starting as a C++ developer, then moving on to databases. For the past six years he’s been working as a web-developer working in the JavaScript ecosystem, and developing web-apps in ReactJS, NodeJS, GraphQL. He loves to blog about what he learns and what he’s up to.