DEV Community

Felippe Regazio
Felippe Regazio

Posted on • Updated on


A tiny "Deployer" made with Shell Script and Rsync

So, there is all that stuff outside there, huhn? Containers, Continuous Integration, Git Deployment, Pipes etc. And they are awesome, in fact.

But sometimes we have a legacy project in hand, some old stuff or huge infrastructure monoliths that are simply really risky to refactoring.

Start a deployment strategy on those kind of projects can become a real nightmare. I commonly see people configuring environments from scratch, then using FTP clients as FileZilla, or terminal commands like rsync and scp repeatedly to keep the project up to date.

Thinking in structures like that i wrote a tiny really simple deployer using shell script and rsync. Of course, the main feature here is sync files between your local project and the server. You can add multiple hosts, and can achieve certain level of automation, but this is not comparable (of course) with any of the real deployment technologies that we have today. In fact, the name "Deployer" here is more
illustrative and generated by what it tries to remedy than by what it really does.

No more bla bla bla, lets configure it:

You will need:

A *Unix local system with rsync and git installed.
A *Unix server with Rsync and SSH connection enabled.

Most of this requirements are just a default configuration for any *Unix system. Now, follow this steps:

  1. Clone or download the project on github:

  2. Copy the file and the deploy folder to your project root.

  3. Open the file deploy/, you will see 2 arrays with some fake information. Each array is a valid deployer host, it tells rsync which connection and path to use when syncing. You can add how many as you want in order to deploy to multiple targets for example. Delete the "another" array, and let only the "default". Configure it like that:

declare -a default=(
Enter fullscreen mode Exit fullscreen mode

On the 1st line, the one with root@, you add your ssh connection following the pattern user@host. If you need to pass a different port, use it like that user@host:port.

On the 2nd line you must add the absolute path to your project ON THE SERVER. To discover your project absolute path, access your server using ssh, navigate to your project root folder, and type pwd. Dont use filezilla or GUI clients as reference to find out the root path.

On the 3th line you must add the project IP or URL. The deployer wont use it, but maybe you will need it to extend functionalities, or to remind you about where this project lives.

  1. Now open the deploy/directories.txt file, and add the paths or files that you want to upload, they must be relative to your project root and separated by a blank line. The default directory to sync is ".", or: the entire root folder.

  2. Now open the deploy/ignore.txt and add the paths or files in the same way you did with the directories.txt. This paths, rules or files will be ignored by rsync.

  3. Now open the deploy/remind.txt and add some message. This message will be showed every time you run the script. This step is optional.

Now you are ready to go. Give the file permission to be executed. Open a terminal on your project root and run:

Enter fullscreen mode Exit fullscreen mode

You could run it using sh, but as pointed out by @tonypelliccio in the comments:

From a systems perspective you don't need to launch a new shell by using sh. Instead ./ whilst in the same directory will work too. And if you have to be root sudo su - will work just as well.

When you run it for the first time, rsync will sync your local project with the server one. Now, when you modify something on your project, just run de deployer and it will sync only the modified files, based on your configuration. A log will be saved on ./deploy/logs.

You can add new entries on and call them as a parameter. For example, if we had configured the "another" array on, we could use it like that:

./ another
Enter fullscreen mode Exit fullscreen mode

At the end, its just the good and old rsync. But this script brings automation and standardization to the deployment process on old systems.
See the on github to know more about, or feel free to message me. And again: this is not an ideal modern solution, its a script to solve a problem that you may have with legacy infra structures, old projects, poor hosts, etc. Dont know your situation, but may this could be useful for you, and thats the point. Thank you for your interest, thats all folks.

Top comments (7)

syntaxseed profile image
SyntaxSeed (Sherri W) • Edited

2 hours of learning Ansible & I had the same kind of thing working on a legacy app.

This even worked on a shared host with no root access.

Might make more sense to spend effort on a tool that can scale with you.

juliomaranhao profile image
Júlio Maranhão

Ansible needs python at remote site. Sure many distros already have python in default installation. But if python is not available (legacy, old, no-auth?) or you prefer shell scripting, than sh-simple-deployer and cdist are good candidates.

I prefer Ansible but it's not a 2 h tool. Only if I want to print Hello World. Ansible manual is vast and I need a lot of the modules and other concepts (roles, yaml, Jinja, etc) to really say "Wow, this is better/faster than scripting". Maybe a week. :-)

syntaxseed profile image
SyntaxSeed (Sherri W) • Edited

Good point about the python dependency! If you don't have that, it won't work.

But I wasn't exaggerating about the 2 hours to get a useful versioned deploy from Git working. I used the Deploy Helper module as a starting point:

felipperegazio profile image
Felippe Regazio

I didn't knew Ansible. Seems really simple and powerful, indeed. I'll try to use it, for sure.

iarehilton profile image
Hilton Meyer

Always good to see someone else using this. I actually have something similar that I did a week or so ago that I also wrote about. I clone the repo and then used rsync to my site directory. Great for older hosting models

tonypelliccio profile image
Tony Pellicccio

From a systems perspective you don't wan to launch a new shell by using sh. Instead ./ whilst in the same directory will work too. And if you have to be root sudo su - will work just as well.

felipperegazio profile image
Felippe Regazio • Edited

Nice point, Tony. You're right. I updated the post with your information.