Ubuntu Server 18.04 – Writing simple scripts

How to install and use docker on ubuntu 18.04

This is the section were everything we’ve talked about so far starts to come together. Scripting can be very fun and rewarding, as they allow you to automate large jobs or just simplify something that you find yourself doing over and over. The most important point about scripting is this: if it’s something you’ll be doing more than once, you really should be making into a script. This is a great habit to get into.

A script is a very simple concept. A script is just a text file, that contains commands for your shell to execute one by one. A script written to be executed by Bash is known as a Bash script, and that’s what we’ll work on creating in this section.

At this point, I’m assuming that you’ve practiced a bit with a text editor in Linux. It doesn’t matter if you use vim or the simpler nano. Since we’ve edited text files before, I’m under the assumption that you already know how to create and edit files. If not, all you really need to know is that nano is a good text editor to begin with and is simple to use.

There’s a big chance that at some point in your Linux career, you’ll gravitate toward vim; almost everyone does (unless you’re one of those people that use emacs, for some reason). If in doubt, just stick with nano for now.

Basic usage of nano is really easy: all you need to do is give the nano command a path and filename. You don’t actually have to give it a filename, but I find it easier to do so. After you’ve typed some content, you can press Ctrl + O to save and then Ctrl + X to exit the editor. To get started, let’s create a simple script so we can see what the process looks like:

nano ~/myscript.sh
If you weren’t already aware, a tilde (~) is just a shortcut for a user’s home directory. Therefore, on my system, the previous command would be the same as if I had typed:

nano /home/jay/myscript.sh

Inside the file, type the following:

#!/bin/bash
echo "My name is $USER"
echo "My home directory is $HOME"

Save the file and exit the editor. In order to run this file as a script, we need to mark it as executable:

chmod +x ~/myscript.sh

To execute it, we simply call the path to the file and the filename:

~/myscript.sh

The output should look similar to the following:

"My name is jay"
"My home directory is /home/jay"

The first line might seem strange if you haven’t seen it before. Normally, lines starting with a hash symbol (#) are ignored by the interpreter. The one on the first line is an exception to this. The #!/bin/bash we see on the 1st line, this is known as a hash bang, or shebang. Basically, it just tells the shell which interpreter to use to run the commands inside the script. There are other interpreters we could be using, such as #!/usr/bin/python if we were writing a script in the Python language. Since we’re writing a bash script, we used #!/bin/bash.

The lines that followed were simple print statements. Each one used a system variable, so you didn’t have to declare any of those variables as they already existed. Here, we printed the current user’s username, home directory, and default text editor.

The concept of scripting becomes more valuable when you start to think of things you do on a regular basis that you can instead automate. To be an effective Linux administrator, it’s important to adopt the automation mindset. Again, if you are going to do a job more than once, script it. Here’s another example script to help drive this concept home. This time, the script will actually be somewhat useful:

#!/bin/bash 
sudo apt install apache2 
sudo apt install libapache2-mod-php7.2 
sudo a2enmod php 
sudo systemctl restart apache2 

We haven’t gone over any advanced shell concepts yet, so this will do for now. But what we’ve done is theoretically scripted the setup of a web server. We could extend this script further by having it copy site content to /var/www/html, enable a configuration file, and so on. But from the preceding script, you can probably see how scripting can be useful in condensing the amount of work you do. This script could be an advanced web server install script, that you could simply copy to a new server and then run.

Now, let’s get a bit more advanced with scripting. The previous script only installed some packages, something we probably could’ve done just as easily by copying and pasting the commands into the shell. Let’s take this script a bit further. Let’s write a conditional statement. Here’s a modified version of the previous script:

#!/bin/bash 
 
# Install Apache if it's not already present 
if [ ! -f /usr/sbin/apache2 ]; then 
    sudo apt install -y apache2 
    sudo apt install -y libapache2-mod-php7.2 
    sudo a2enmod php 
    sudo systemctl restart apache2 
fi 

Now it’s getting a bit more interesting. The first line after the hash bang is a comment, letting us know what the script does:

# Install Apache if it's not already present 

Comments are ignored by the interpreter but are useful in letting us know what a block of code is doing.

Next, we start an if statement:

if [ ! -f /usr/sbin/apache2 ]; then

Bash, like any scripting language, supports branching and the if statement is one way of doing that. Here, it’s checking for the existence of the apache2 binary. The -f option here specifies that we’re looking for a file. We can change this to -d to check for the existence of a directory instead. The exclamation mark is an inverse, it basically means we’re checking if something is not present. If we wanted to check if something is present, we would omit the exclamation mark. Basically, we’re setting up the script to do nothing if Apache is already installed. In this case, inside the brackets we are just executing a shell command, and then the result is checked.

The commands sandwiched inside the if statement are simply installing packages. We use the -y option here, because in a script we probably don’t want to have it wait for confirmation. Normally, I don’t like using the -y option, but in a script it’s perfectly acceptable.

Finally, we close out our if statement with the word if backwards (fi). If you forgot to do this, the script will fail.

In regard to the concept of if statements, we can compare values as well. Consider the following example:

#!/bin/bash 
myvar=1 
if [ $myvar -eq 1]; then 
    echo "The variable equals 1" 
fi 

With this script, we’re merely checking the contents of a variable, and taking action if it equals a certain number. Notice we didn’t use quotation marks when creating the variable. We just set a number (integer) here, so we would’ve only used quotation marks if we wanted to set a string. We can also take action if the if statement doesn’t match:

#!/bin/bash 
myvar=10 
if [ $myvar -eq 1]; then 
    echo "The variable equals 1" 
else 
    echo "The variable doesn't equal 1" 
fi 

This was a silly example, I know, but it works as far as illustrating how to create an if/else logic block in Bash. The if statement checks to see if the variable was equal to 1. It isn’t, so the else block executes instead.

The -eq portion of the command is similar to == in most programming languages. It’s checking to see whether the value is equal to something. Alternatively, we can use -ne (not equal), -gt (greater than), -ge (greater than or equal to), -lt (less than), and so on.

At this point, I recommend you take a break from reading to further practice scripting (practice is key to committing concepts to memory). Try the following challenges:

  • Ask the user to enter input, such as their age, and save it to a variable. If the user enters a number less than 30, tell them they’re young. If the number is equal to or greater than 30, echo a statement telling them that they’re old.
  • Write a script that copies a file from one place to another. Make the script check to see whether that file exists first, and have an else statement printing an error if the file doesn’t exist.
  • Think about any topic we’ve already worked on during this tutorial, and attempt to automate it.

Now, let’s take a look at another concept, which is looping. The basic idea behind looping is simply do something repeatedly until some condition has been met. Consider the following example script:

#!/bin/bash 
myvar=1 
while [ $myvar -le 15 ] 
do 
    echo $myvar 
    ((myvar++)) 
done 

Let’s go through the script line by line to understand what it’s doing.

myvar=1 

With this new script, we’re creating a control variable, called myvar, and setting it equal to 1.

while [ $myvar -le 15 ]

Next, we set up a while loop. A while loop will continue until a condition is met. Here, we’re telling it to execute the statements in the block over and over until $myvar becomes equal to 15. In fact, a while loop can continue forever if you enter something incorrectly, which is known as an Infinite Loop. If you used -ge 0 instead, you would’ve created exactly that.

echo $myvar

Here, we’re printing the current content of the $myvar variable, nothing surprising here.

((myvar++))

With this statement, we’re using what’s known as an incrementer to increase the value of our variable by 1. The double parenthesis tells the shell that we’re doing an arithmetic operation, so the interpreter doesn’t think that we’re working with strings.

done

When we’re done writing a while loop, we must close the block with done. If you’ve typed the script properly, it should count from 1 to 15.

Another type of loop is a For Loop. A for loop executes a statement for every item in a set. For example, you can have the for loop execute a command against every file in a directory. Consider this example:

#!/bin/bash
turtles='Donatello Leonardo Michelangelo Raphael'
for t in $turtles
do
echo $t
done

Let’s take a deeper look into what we’ve done here.

turtles='Donatello Leonardo Michelangelo Raphael'

Here, we’re creating a list and populating it with names. Each name is one item in the list. We’re calling this list turtles. We can see the contents of this list with echo as we would with any other variable:

echo $turtles

Next, let’s look at how we set up the for loop:

for t in $turtles

Now, we’re telling the interpreter to prepare to do something for every item in the list. The t here is arbitrary, we could’ve used any letter here or even a longer string. We’re just setting up a temporary variable we want to use in order to hold the current item the script is working on.

do

With do, we’re telling the for loop to prepare itself to start doing something.

echo $t

Now, we’re printing the current value of $t to stdout.

done

Just as we did with the while loop, we type done to let the interpreter know this is the end of the for loop. Effectively, we just created a for loop to print each item in a list independently. We included four turtle names in our list.

Feel free to practice the concepts I listed here until you get the hang of everything. If you want to explore further, I have an entire series about Bash scripting on my YouTube channel you can use to expand your knowledge. Check out the Further reading section for the URL.

Comments are closed.