Programster's Blog

Tutorials focusing on Linux, programming, and open source

Ansible - Run A Local Script On Remote Server

Let's imagine you have a script to set up your servers from scratch. In this case, let's call it setup.sh and for now, it will just be a BASH script that updates a debian/ubuntu server and installs git.

This will work with any type of script, it doesn't have to be bash

This tutorial uses the script core module, which was intoroduced in Ansible 1.5 so you should almost definitely have it.

Steps

Create the Setup Script

Lets create the script on our Ansible server because it needs to be local.

#!/bin/bash
sudo apt update
sudo apt-get dist-upgrade -y
sudo apt-get install git -y

For this tutorial I have put it in /home/stuart/scripts/setup.sh.

Update The Hosts File

If your starting out, then you need to create a group in your hosts file that we will run the setup script on. For this tutorial, my group is my-servers.

Create the Playbook

Now we need to create the ansible playbook that will transfer that script to the remote server(s) and execute it. For this tutorial, I am calling it setup.yml.

- hosts: my-servers
  sudo: true
  tasks:
    - script: /home/stuart/scripts/setup.sh

Execute!

Now run the following command to execute your script. You may or may not need to swap out the $USER variable.

ansible-playbook setup.yml --user=$USER

The user you connect with will need passwordless sudo privileges.

Taking It Further

If you want to ensure that your script only ever gets executed once, then you can simply tweak your playbook to be like this:

- hosts: my-servers
  sudo: true
  tasks:
    - script: /home/stuart/scripts/setup.sh --creates /home/stuart/installed-git.txt

You will see that we added --creates which specifies the location of a file to check and if it exists, our script will not be executed. It does not implicitly create a blank file at that location, or pipe all the output to that location. Hence we need to update our local script to create that file so that subsequent calls will not be executed.

#!/bin/bash
sudo apt update
sudo apt-get dist-upgrade -y
sudo apt-get install git -y

# Create our file to check for in future
echo "installed git!" >> /home/stuart/installed-git.txt

Removes Option

If we created an uninstall script, we would want that to also only executed once, and only if we have already executed the installation script. Thus we would want to check if the installed-git.txt file exists, and only run if it doesn't. Luckily the --removes option provides this functionality.

For this, our uninstall.yml playbook would be like so:

- hosts: my-servers
  sudo: true
  tasks:
    - script: /home/stuart/scripts/uninstall-git.sh --removes /home/stuart/installed-git.txt

Our local uninstall-git.sh script would be like so:

#!/bin/bash
sudo apt-get remove git -y

# Remove our file
rm /home/stuart/installed-git.txt

Just like the --creates option, it does not implicitly remove the file for you, it only make ansible execute the script the file already exists. Your script has to remove the file.

References