Dev Ops
Dev Ops
Bash Scripting
by Imran Teli @VisualPath
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.
DEVOPS
also be run normally on the command line and it will
do exactly the same thing.
by Imran Teli @VisualPath
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:
Line 2:
Line 3:
Is the command echo which will print a message to the
DEVOPS
screen. You can type this command yourself on the
command line and it will behave exactly the same.
by Imran
Running Or Teli @VisualPath
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.
imran@DevOps:.../bash$ ./print.sh
bash: ./print.sh: Permission denied
imran@DevOps:.../bash$ ls -l
total 4
-rw- rw-r- - 1 imran imran 53 Oct 21 17:33 print.sh
imran@DevOps:.../bash$ chmod 755 print.sh
imran@DevOps:.../bash$ ls -l
total 4
-rwxr- xr-x 1 imran imran 53 Oct 21 17:33 print.sh
imran@DevOps:.../bash$ ./print.sh
Hello World!
by Imran
How Do They Teli @VisualPath
Work?
A variable is a temporary store for a piece of information.
There are two actions we may perform for variables:.
imran@DevOps:.../bash$ VAR1=123
imran@DevOps:.../bash$ echo $VAR1
123
cp $1 $2
# Let's verify the copy worked
echo Details for $2
ls -lh $2
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.
DEVOPS
ls $DIR_PATH
DEVOPS
imran@DevOps:.../bash$ echo $newvar
More $myvar
by Imran Teli @VisualPath
imran@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..
1.imran@DevOps:.../testcopy$ file=`ls`
imran@DevOps:.../testcopy$ echo $file
copyscript.sh dir1 dir2
imran@DevOps:.../testcopy$ files=$(ls)
imran@DevOps:.../testcopy$ echo $files
copyscript.sh dir1 dir2
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.
DEVOPS
There are two syntax for doing this.
by Imranfrom
Export a variable Teli @VisualPath
bash shell as mentioned below.
imran@DevOps:.../bash$ var1=foo
imran@DevOps:.../bash$ echo $var1
foo
imran@DevOps:.../bash$ export var1
imran@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
imran@DevOps:.../bash$ ./script1.sh
~/.profile
~/.bashrc
/etc/profile
For Example:
Summary:
$1, $2, ...
Quotes "
variable=value
To set a value for a variable. Remember, no spaces on
DEVOPS
either side of =
export var1
read var1
Let's look at a simple example:
input.sh
1.#!/bin/bash
2. # Ask the username
3. echo “Please enter the username”
4. read varname
5. echo “Welcome back $varname”
imran@DevOps:.../bashscripts$ ./input.sh
DEVOPS
Please enter the username
DevTestOps
by Imran Teli @VisualPath
Explanation:
Line 3 - Print a message asking the user for input.
Line 4 - Run the command read and save the users
response into the variable varname
Line 5 – echo another message just to verify the read
command worked. Note: I had to put a backslash ( \ )
in front of the ' so that it was escaped.
Login.sh
#!/bin/bash
# Ask the user for login details
read -p 'Username: ' uservar
read -sp 'Password: ' passvar
echo
echo Thankyou $uservar we now have your login
details
So far we have looked at a single word as input. We can do
DEVOPS
more than that however.
#!/bin/bash
# Demonstrate how read actually works
echo Enter your Name, Profession & Interests in
same order seprated by a space?
read name profession interest
echo Your entered name is: $name
echo Your profession is: $profession
echo Your are interested in: $interest
imran@DevOps:.../bashscripts$ ./multiinput.sh
Enter your Name, Profession & Interests in same
order seprated by a space?
Imran DevOps Hiking
Your entered name is: Imran
Your profession is: DevOps
Your are interested in: Hiking
If Statements
Scripts making decisions.
Basic If Statements
If you use bash for scripting you will undoubtedly have to
use conditions a lot. Based on a condition you decide if
you should execute some commands on the system or not.
A basic if statement effectively says, if a particular test is
true, then perform a given set of actions. If it is not true
then don't perform those actions. If follows the format
DEVOPS
below:
if_example.sh
#!/bin/bash
# Basic if statement
if [ $1 -gt 100 ]
then
echo Hey that’s a large number.
pwd
fi
DEVOPS
date
Test
The square brackets ( [ ] ) in the if statement above are
actually a reference to the command test. This means that
all of the operators that test allows may be used here as
well. Look up the man page for test to see all of the
possible operators (there are quite a few) but some of the
more common ones are listed below.
Operator Description
The for loop will take each item in the list (in order, one
after the other), assign that item as the value of the
variable var, execute the commands between do and done
then go back to the top, grab the next item in the list and
repeat over. The list is defined as a series of strings,
separated by spaces.
Example:
The contents of $Variable is printed three times.
#!/bin/bash
for Variable in {1..3}
do
DEVOPS
echo "$Variable"
done
by Imran Teli @VisualPath
While Loop
The bash while loop is a control flow statement that allows
DEVOPS
code or commands to be executed repeatedly based on a
given condition. For example, run echo command 5 times
by Imran Teli @VisualPath
or read text file line by line or evaluate the options passed
on the command line for a script.
Syntax:
The syntax is as follows:
while [ condition ]
do
command1
command2
command3
done
#!/bin/bash
a=1
while [ $a -le 5 ]
do
echo "Number $a"
x=$(( $x + 1 ))
done
Printing List Of Host IP Addresses From Hosts File.
DEVOPS
Create a file named hosts
$ vi hosts
by Imran Teli @VisualPath
192.168.1.10
192.168.1.11
192.168.1.12
192.168.1.13
#!/bin/bash
Explanation
Line 1. For command substitution we are using backticks
`` . It’s different from single quote ‘’ `cat hosts` will return
the content of hosts file line by line, which will be stored
in variable “i”.
Real time use cases
Bash script to install Apache, MYSQL and PHP for
Ubuntu OS.
DEVOPS
other characters: ”<Esc>[FormatCodem”.
by <Esc>
In Bash, the Imran Teli @VisualPath
character can be obtained with the
following syntaxes:
\e
\033
\x1B
#!/bin/bash
#COLORS
# Reset
Color_Off='\033[0m' # Text Reset
# Regular Colors
Red='\033[0;31m' # Red
Green='\033[0;32m' # Green
Yellow='\033[0;33m' # Yellow
Purple='\033[0;35m' # Purple
Cyan='\033[0;36m' # Cyan
# Update packages and Upgrade system
echo -e "$Cyan \n Updating System.. $Color_Off"
sudo apt-get update -y && sudo apt-get upgrade -y
## Install AMP
echo -e "$Cyan \n Installing Apache2 $Color_Off"
sudo apt-get install apache2 apache2-doc apache2-
mpm- prefork apache2-utils libexpat1 ssl- cert -y
echo -e "$Cyan \n Installing PHP & Requirements
$Color_Off"
sudo apt-get install libapache2-mod- php5 php5
php5-common php5-curl php5-dev php5-gd
php5-idn php-pear php5-imagick php5-mcrypt php5-
DEVOPS
mysql php5-ps php5-pspell php5-recode
php5-xsl -y
by Imran Teli @VisualPath
echo -e "$Cyan \n Installing MySQL $Color_Off"
sudo apt-get install mysql-server mysql-client
libmysqlclient15.dev -y
echo -e "$Cyan \n Installing phpMyAdmin
$Color_Off"
sudo apt-get install phpmyadmin -y
echo -e "$Cyan \n Verifying installs$Color_Off"
sudo apt-get install apache2 libapache2-mod- php5
php5 mysql-server php-pear php5-mysql
mysql-client mysql-server php5-mysql php5-gd -y
## TWEAKS and Settings
# Restart Apache
echo -e "$Cyan \n Restarting Apache $Color_Off"
sudo service apache2 restart
Backup Scripts
Being working with systems you may need to take backup
DEVOPS
of files, directories, log files etc. Below mention scenario
shows you how you can automate the backup procedures.
by Imran Teli @VisualPath
In this example, we will create a file and mention the
name of log files that needs to be backup up with tar
command. Before taking backup, our script will also tell
us if the log file exists or not. It will skip the backup
procedure if the file does not exists. After all there is no
point running backup command if the log file does not
exist..
$ mkdir -p /tmp/scripts/logs
$ cd /tmp/scripts/logs
$ touch ansible.log apache.log mysql.log nagios.log
You can choose to put some content in the log files, touch
will just create empty files.
$ cd /tmp/scripts
Create a file where you place the name of the files that you
want to backup.
$ vi backup_files.txt
DEVOPS
apache.log
mysql.log
by Imran Teli @VisualPath
nagios.log
ansible.log
chef.log
$ vi backup.sh
#!/bin/bash
LOG_DIR='/tmp/scripts/logs'
BACKUP_DIR='/tmp/scripts/logs_backup'
mkdir -p $BACKUP_DIR
for i in `cat backup_files.txt`; do
if [ -f $LOG_DIR/$i ];
then
echo "Copying $i to logs_backup directory."
cp $LOG_DIR/$i $BACKUP_DIR
else
echo "$i log file does exist, skipping."
fi
done
echo
echo
echo "Zipping log files"
tar -czvf logs_backup.tgz logs_backup
echo
echo
DEVOPS
echo "Backup completed successfully."
Mysql Database
by ImranBackup Script
Teli @VisualPath
mysqldump command is used to take the db dump for
mysql. In the script, we’re taking the dbdump and sending
it to a target directory in a zipped format. We are also
removing 8 days old dbbackup file by using find
command. This process is called a purging or purging old
backup/log files.
#!/bin/sh
TIME_NOW="$(date
+'%d_%m_%Y_%H_%M_%S')"
BACKUPFILE="db_backup_$TIME_NOW".gz
BACKUP_DIR="/opt/db_backup_dir"
PATHOFBACKUPFILE="$BACKUP_DIR/$BACKUPFILE"
LOG_FILE="$BACKUP_DIR/"backup_log_"$(date
+'%Y_%m')".txt
echo "mysqldump started at $(date +'%d-%m- %Y
%H:%M:%S')" >> "$LOG_FILE"
mysqldump -- user=dbuser-- password=dbpass --
default-character- set=utf8 mydatabase |
gzip > "$PATHOFBACKUPFILE"
echo "mysqldump finished at $(date +'%d-%m- %Y
%H:%M:%S')" >> "$LOG_FILE"
chown myuser "$PATHOFBACKUPFILE"
chown myuser "$LOG_FILE"
echo "file permission changed" >> "$LOG_FILE"
find "$BACKUP_DIR" -name db_backup_* -mtime
+8 -exec rm {} \;
echo "old files deleted" >> "$LOG_FILE"
echo "operation finished at $(date +'%d-%m- %Y
DEVOPS
%H:%M:%S')" >> "$LOG_FILE"
echo "*****************" >> "$LOG_FILE"
by Imran Teli @VisualPath
exit 0
$ vi hosts-dev
192.168.2.5
192.168.2.6
192.168.2.7
do
ssh vagrant@$hosts sudo yum install httpd -y
done
DEVOPS
virtual private server with SSH than using a password
alone. While a password can eventually be cracked with a
by Imran Teli @VisualPath
brute force attack, SSH keys are nearly impossible to
decipher by brute force alone. Generating a key pair
provides you with two long string of characters: a public
and a private key. You can place the public key on any
server, and then unlock it by connecting to it with a client
that already has the private key. When the two match up,
the system unlocks without the need for a password. You
can increase security even more by protecting the private
key with a passphrase.
DEVOPS
having to type it in each time you use the Key Pair.
The entire by
keyImran Teli @VisualPath
generation process looks like this:
$ ssh-keygen -t rsa
DEVOPS
/home/demo/.ssh/id_rsa.pub The private key
(identification) is now located in /home/demo/.ssh/id_rsa
by Imran Teli @VisualPath
Step Three—Copy The Public Key
The above process is also called a Code Delivery Pipeline.
Once the key pair is generated, it's time to place the public
key on the virtual server that we want to use. You can copy
the public key into the new machine's authorized keys file
with the ssh-copy- id command. Make sure to replace the
example username and IP address below.
$ ssh-copy- id user@192.168.2.5
DEVOPS
weren't expecting. Now you can go ahead and log
into user@192.168.2.5 and you will not be prompted
by Imran Teli @VisualPath
for a password. However, if you set a passphrase,
you will be asked to enter the passphrase at that time
(and whenever else you log in in the future).
Exercise:
-Create 4 centos vm’s. One among these four vm one will
be the automation box from where we will run our scripts.
#!/bin/bash
# Sample script to automate tasks:
# -Update local file database:
echo -e "\e[4;32mInstalling mlocate\e[0m"
sudo yum install mlocate -y
echo ""
DEVOPS
echo -e "\e[4;32mUPDATING LOCAL FILE
DATABASE\e[0m"
by Imran Teli @VisualPath
sudo updatedb
if [ $? == 0 ]; then
echo "The local file database was updated correctly."
else
echo "The local file database was not updated
correctly."
fi
echo ""
# Installing and staring HTTPD service
echo -e "\e[4;32mInstalling HTTPD package\e[0m"
sudo yum install httpd -y
echo ""
echo -e "\e[4;32mStarting and enabling HTTPD
package\e[0m"
sudo /etc/init.d/httpd start && chkconfig httpd on
Visualpath Training & Consulting DevOps
Ph: 97044 55959, 96182 45689,
onlinevisualpath@gmail.com, wwwvisualpath.in# 27
echo ""
# For CentOS 7
#sudo systemctl start httpd && sudo systemctl
enable httpd
# -Find and / or delete files with 777 permissions.
echo -e "\e[4;32mLOOKING FOR FILES WITH
777 PERMISSIONS\e[0m"
# Enable either option (comment out the other line),
but not both.
# Option 1: Delete files without prompting for
confirmation. Assumes GNU version of find.
#find -type f -perm 0777 -delete
DEVOPS
# Option 2: Ask for confirmation before deleting
files. More portable across systems.
by Imran Teli @VisualPath
find -type f -perm 0777 -exec rm -f {} +;
echo ""
# -Alert when file system usage surpasses a defined
limit
echo -e "\e[4;32mCHECKING FILE SYSTEM
USAGE\e[0m"
THRESHOLD=10
while read line; do
# This variable stores the file system path as a string
FILESYSTEM=$(echo $line | awk '{print $1}')
# This variable stores the use percentage (XX%)
PERCENTAGE=$(echo $line | awk '{print $5}')
# Use percentage without the % sign.
USAGE=${PERCENTAGE%?}
if [ $USAGE -gt $THRESHOLD ]; then
echo "The remaining available space in
$FILESYSTEM is critically low. Used:
$PERCENTAGE"
fi
done < <(df -h -- total | grep -vi filesystem)
DEVOPS
cat nginstart.sh
# crontab -e
* * * * * /opt/scripts/nginstart.sh
#!/bin/bash
# Author: Pavan Kumar Ranjit
## LOGIC TO CHECK THE TYPE OF
DISTRIBUTION (REDHAT OR DEBIAN)
yum -- help >> /tmp/log1
if [ $? -eq 0 ]
## "$?" STORES THE EXIT CODE OF THE MOST
RECENT COMMAND
then
echo "RPM Based OS Detected"
echo "Installing Java-JDK,Jenkins,Maven"
sleep 3
sudo yum install java-1.8.0- openjdk -y
sudo yum install java-1.8.0- openjdk-devel -y
DEVOPS
sudo yum install wget -y
sudo wget -O /etc/yum.repos.d/jenkins.repo
by Imran Teli @VisualPath
http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm -- import https://jenkins-
ci.org/redhat/jenkins- ci.org.key
sudo yum install Jenkins -y
sudo yum install maven -y
sudo yum install git -y
echo "Configuring services.... Please Wait"
sleep 5
sudo service iptables stop
sudo service Jenkins start
else
echo "Debian Based OS Detected"
sleep 3
echo "Installing Java-JDK,Jenkins,Maven"
sudo apt-get update
sudo apt-get install openjdk-8- jdk -y
sudo apt-get install openjdk-8- jre -y
sudo apt-get install maven -y
sudo apt-get install wget -y
wget -q -O - https://pkg.jenkins.io/debian/jenkins-
ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-
stable binary/ >
/etc/apt/sources.list.d/jenkins.list'
sudo apt-get update -y
sudo apt-get install jenkins -y
sudo apt-get install git -y
echo "Configuring services.... Please Wait"
sleep 5
sudo systemctl stop ufw
DEVOPS
sudo systemctl start jenkins
fi
by Imran Teli @VisualPath
For Example:
AWS
Azure
Google Cloud
Rackspace
Monitoring Tools:
Is used to monitor our infrastructure and application
health. It sends us notifications and reports through email
or other means.
Summary:
Conclusion:
Bash way
#!/bin/bash a=5
if [ $a -lt 10 ]
then
echo "Variable is smaller than 10"
exit 1
fi
Python way
#!/usr/bin/python
a=10
if a < 10:
print “variable is less than 10”
DEVOPS
anything.
by Imran
Practice makes Teli @VisualPath
improvement.