Bash Scripting | Visualpath

Bash Scripting

Introduction

This tutorial will give you a solid platform in how to create bash scripts and automate day to day system admin tasks. Certainly, everything cannot be covered in this chapter but you will be equipped with right amount of knowledge to make your own scripts and excel in it if you put in your own efforts. Bash scripting is used by many of the system admins and DevOps geeks to get things done quickly and efficiently. There are so many automation tools in the market like Ansible, Puppet, Chef etc. Which are way more sophisticated but sometimes to get things done quickly in Linux systems we use Bash scripts. Also, scripting will make you understand what automation means and then you can quickly grasp the features that is used in Configuration Management tools like Ansible or puppet.
What are scripts?
A Bash script is a plain text file which contains a series of commands. These commands are a mixture of commands we would normally type ourselves on the command line (such as ls or cp for example) and commands we could type on the command line but generally wouldn't (you'll discover these over the next few pages). A crucial point to remember though is:
Anything you can run normally on the command line can be put into a script and it will do exactly the same thing. Similarly, anything you can put into a script can also be run normally on the command line and it will do exactly the same thing.
First Script
As we discussed earlier that script is a normal text file with commands in it. We will open a file vi editor and add some commands in it. It is convention to give files that are Bash scripts an extension of .sh (print.sh for example)

$ vi print.sh

1. #!/bin/bash
2. # A sample Bash script
3. echo Hello World!

Explanation:

Line 1:
#! is called as the SHEBANG character, it tells the script to interpret the rest of the lines with an Interpreter /bin/bash. So, if we change that to /usr/bin/python then it tells the script to use python interpreter.
Line 2:
This is a comment. Anything after # is not executed. It is for our reference only. Comments is for us so or anybody who reads this script will have some reference.
Line 3:
Is the command echo which will print a message to the screen. You can type this command yourself on the command line and it will behave exactly the same.
Running or Executing a script?
Running a Bash script is fairly easy. Sometimes you will hear people saying execute the script, both means same thing. Before we can execute a script, it must have the execute permission set. If you forget to grant this permission before running the script you'll just get an error message “Permission denied”. Whenever you create a file in Linux system by default it will not have an execute permission, this is for security reasons. You make your script executable and then you can run it.

admin@DevOps:.../bash$ ./print.sh
bash: ./print.sh: Permission denied
admin@DevOps:.../bash$ ls -l
total 4
-rw- rw-r- - 1 imran imran 53 Oct 21 17:33 print.sh
admin@DevOps:.../bash$ chmod 755 print.sh
admin@DevOps:.../bash$ ls -l
total 4
-rwxr- xr-x 1 imran imran 53 Oct 21 17:33 print.sh
admin@DevOps:.../bash$ ./print.sh
Hello World!

Without giving execute permission also we can run the script but then we provide a shell and ask it to run all the command in the script on that shell.
admin@DevOps:.../bash$ bash print.sh
Hello World!

Variables

Temporary stores of information in memory.
How do they Work?
A variable is a temporary store for a piece of information. There are two actions we may perform for variables:.
Setting a value for a variable.
Reading or using the value for a variable.
To assign a variable we use = sign, VariableName=Value
To read/access the value of variable we use $VariableName

admin@DevOps:.../bash$ VAR1=123
admin@DevOps:.../bash$ echo $VAR1
123


Command line arguments

When we run a program on the command line you would be familiar with supplying arguments after it to control its behaviour. For instance we could run the command ls -l /tmp. -l and /tmp are both command line arguments to the command ls. We can do similar with our bash scripts. To do this we use the variables $1 to represent the first command line argument, $2 to represent the second command line argument and so on. These are automatically set by the system when we run our script so all we need to do is refer to them.
Let's look at an example

copyscript.sh
#!/bin/bash
# A simple copy script
cp $1 $2
# Let's verify the copy worked
echo Details for $2
ls -lh $2


admin@DevOps:.../testcopy$ mkdir dir1 dir2
admin@DevOps:.../testcopy$ touch dir1/tesla
admin@DevOps:.../testcopy$ ./copyscript.sh dir1/tesla dir2/
Details for dir2/
total 0
-rw- rw-r- - 1 imran imran 0 Jun 19 23:01 tesla

Explanation:

Line 3- run the command cp with the first command line argument as the source and the second command line argument as the destination.
Line 5 - run the command echo to print a message.
Line 6 - After the copy has completed, run the command ls for the destination just to verify it worked. We have included the options l to show us extra information and h to make the size human readable so we may verify it copied correctly.
Some System Variables
There are a few other variables that the system sets for you to use as well.
$0 - The name of the Bash script.
$1 - $9 - The first 9 arguments to the Bash script. (As mentioned above.)
$# - How many arguments were passed to the Bash script.
$@ - All the arguments supplied to the Bash script.
$? - The exit status of the most recently run process.
$$ - The process ID of the current script.
$USER - The username of the user running the script.
$HOSTNAME - The hostname of the machine the script is running on.
$SECONDS - The number of seconds since the script was started.
$RANDOM - Returns a different random number each time is it referred to.
$LINENO - Returns the current line number in the Bash script.
Setting your own variables

admin@DevOps:~/.../bash_scripts$ cat 1_print.sh
intA=20
floatB=20.20
stringA="first_string"
DIR_PATH="/tmp"
echo echo "#########################"
echo "Value of integer A is $intA"
echo "#########################&qu
echo "Value of Float B is $intB"
echo "#########################"
echo "Value of string A is $stringA"
echo "#########################"
echo "Directory path is $DIR_PATH"
echo "#########################"
echo "Content of TMP directory."
echo "#########################"
ls $DIR_PATH

Quotes
Storing a single word in a variable works fine without quotes, but if we want to store a sentence and also want to store special characters like $,%,@ etc our normal variable assignment will not work.

admin@DevOps:.../bash$ myvar=Hello World
World: command not found imran@DevOps:.../bash$

When we want variables to store more complex values however, we need to make use of quotes. This is because under normal circumstances Bash uses a space to determine separate items.
When we enclose our content in quotes we are indicating to Bash that the contents should be considered as a single item. You may use single quotes ( ' ) or double quotes ( " ). Single quotes will treat every character literally.
Double quotes will allow you to do substitution (that is include variables within the setting of the value).


admin@DevOps:.../bash$ myvar='Hello World'
admin@DevOps:.../bash$ echo $myvar
Hello World
admin@DevOps:.../bash$ newvar="More $myvar"
admin@DevOps:.../bash$ echo $newvar
More Hello World
admin@DevOps:.../bash$ newvar='More $myvar'
admin@DevOps:.../bash$ echo $newvar
More $myvar
admin@DevOps:.../bash$



Command Substitution

Variable defined in the script leave with it and dies after the script dies or completes. If we want to define a variable that is accessible to all the scripts from your current shell we need to export it..

admin@DevOps:.../testcopy$ file=`ls`
admin@DevOps:.../testcopy$ echo $file
copyscript.sh dir1 dir2

admin@DevOps:.../testcopy$ files=$(ls)
admin@DevOps:.../testcopy$ echo $files
copyscript.sh dir1 dir2

admin@DevOps:.../bash$ myvar=$( ls /etc | wc -l )
admin@DevOps:.../bash$ echo There are $myvar entries in the directory /etc
There are 249 entries in the directory /etc

Exporting Variables

We have how to store a string/text into a variable but sometimes you want to store output of a command to a variable. Like you may need to store of ls command output to a variable. For this we use Command Substitution. There are two syntax for doing this.
Export a variable from bash shell as mentioned below.

admin@DevOps:.../bash$ var1=foo
admin@DevOps:.../bash$ echo $var1
foo
admin@DevOps:.../bash$ export var1

Create a script which prints exported and local variable


admin@DevOps:.../bash$ vi script1.sh
#!/bin/bash
# demonstrate variable scope
var2=foobar
echo "Printing exported varible from bash shell"
echo $var1
echo "Printing varible defined in the script"
echo $var2

Execute the script to see the results

admin@DevOps:.../bash$ ./script1.sh

Printing exported variable from bash shell
foo
Printing variable defined in the script
foobar

Comments