DEV Community

Cover image for Shell Scripting - Zero to Hero
MUHAMMAD ARBAB ANJUM
MUHAMMAD ARBAB ANJUM

Posted on • Edited on

Shell Scripting - Zero to Hero

Shell scripting consists of set of commands to perform a task.

Different types of shells:

  1. bash
  2. sh
  3. ksh
  4. tsh
  5. fish
  6. zsh (Extended version of bash with more advanced features)

What is my shell type?

echo $0
Enter fullscreen mode Exit fullscreen mode

How to check supported shells?

cat /etc/shells
Enter fullscreen mode Exit fullscreen mode

What is shebang?

It specifies which interpreter should be used to execute the script.

#!/bin/bash
Enter fullscreen mode Exit fullscreen mode

Basic shell script

#!/bin/bash
echo "hello world!"
Enter fullscreen mode Exit fullscreen mode

How to execute script?

Make sure script have execute permission rwx.
1- ./file.sh
2- path/file.sh
3- bash file.sh
Enter fullscreen mode Exit fullscreen mode

How to add comments?

1- single line comment 

#comment

2- Multiline comment

<<comment 

---- Your Comment Here ----

comment

Enter fullscreen mode Exit fullscreen mode

Variables:

How to use variables?

#!/bin/bash
person="Arbab Anjum"
hostName=$(hostname)
readonly role="superadmin"

echo $person is using $hostName and role is $role

------
> Output: Arbab Anjum is using ubuntu and role is superadmin
Enter fullscreen mode Exit fullscreen mode

Array:

How to define and get value of an array?

Set Value:

myArray = (1 2 3 Hello "World");

Get Value:

echo "${myArray[0]}"
echo "${myArray[1]}"

Enter fullscreen mode Exit fullscreen mode

How to find length of an array?

echo "${#myArray[*]}"
Enter fullscreen mode Exit fullscreen mode

How to get specific values?

echo "${myArray[*]:1}"
echo "${myArray[*]:1:2}" // from index 1, get 2 values
Enter fullscreen mode Exit fullscreen mode

How to update an array?

myArray+=(New 7 8)
Enter fullscreen mode Exit fullscreen mode

How to store the key value pairs?

declare -A myKeyValArray
myKeyValArray=([name]="Arbab Anjum",[city]="London")
echo "Name is ${myKeyValArray[name]}"
Enter fullscreen mode Exit fullscreen mode

String Operations:

myVar="My name is Muhammad Arbab Anjum"
echo "Length: ${#myVar}"
echo "Uppercase: ${myVar^^}"
echo "Length: ${myVar,,}"
echo "Replace (name) with (Name): ${myVar/name/Name}"
echo "Slice: ${myVar:6:13}" 
Enter fullscreen mode Exit fullscreen mode

User Interaction:

echo "What is your name? "
read name
echo "Name is $name"
Enter fullscreen mode Exit fullscreen mode

read in same line:

read -p "What is your name: " name
echo "My name is $name"
Enter fullscreen mode Exit fullscreen mode

Arithmetic Operations

x=10
y=2
let mul=$x*$y # use 'let' to tell it's a mathematical operation
echo "Multiplication: $mul"
echo "Addition: $(($x+$y))"
Enter fullscreen mode Exit fullscreen mode

Conditional Statement

If Else

Example: 1

if [[ $marks -gt 40 ]]
then
    echo "Pass!"
else
    echo "Fail!"
fi
Enter fullscreen mode Exit fullscreen mode

Example: 2

if [[ $marks -gt 40 ]]
then
    echo "Above 40!"
elif [[ $marks -eq 30 ]]
    echo "Fail!"
then
    echo "Equal 30!"
else
    echo "Less than 30!"
fi

Enter fullscreen mode Exit fullscreen mode

Example: 3 || Logical operation

if [[ $age -gt 18 ]] && [[ $country -eq "London" ]]
then
    echo "Pass!"
else
    echo "Fail!"
fi
Enter fullscreen mode Exit fullscreen mode
Equal > -eq/==
Greater than or equal to > -ge
Less than or equal to > -le
Not equal to > -ne/!=
Greater than > -gt
Less than > -lt
Enter fullscreen mode Exit fullscreen mode

Switch Case

echo "Choose an option below:"
echo "a =  To see current data"
echo "b =  list all files in current directory"

read choice

case $choice in
    a) date;;
    b) ls;;
    *) echo "Not a valid input"
esac
Enter fullscreen mode Exit fullscreen mode

For Loop

Example: 1

for i in 1 2 3 4 5
do
      echo "Number: $i"
done
Enter fullscreen mode Exit fullscreen mode

Example: 2

for i in {1..10}
do
      echo "Number: $i"
done
Enter fullscreen mode Exit fullscreen mode

Example: 3 - Getting value from file name.txt

FILE='/home/arbab/name.txt'
for name in $(cat $FILE)
do
      echo "Name is: $name"
done
Enter fullscreen mode Exit fullscreen mode

Example: 4 - Getting value from file name.txt

myArray=(1 2 3 4 5 6 7)
for (( i=0; i<${#myArray[*]}; i++ ))
do
      echo "Value is: ${myArray[$i]}"
done
Enter fullscreen mode Exit fullscreen mode

while Loop

Code keeps executing till the statement is true

count=0
num=10

while [ $count -le $num ]
do
    echo "Number: $count"
    let count++
done
Enter fullscreen mode Exit fullscreen mode

Until loop

Code keeps executing till the statement is false

a=10

until[ $a -eq 1 ]
do
    echo "Number: $a"
    let a--
done
Enter fullscreen mode Exit fullscreen mode

Read content from CSV file

while IFS="," read f1 f2 f3
do
    echo "$f1"
    echo "$f2"
    echo "$f3"
done < file_name.csv
Enter fullscreen mode Exit fullscreen mode

Function

Example 1:

function myFun{
    echo "--------"
    echo "Welcome"
    echo "--------"
}

# Calling Function
myFunc
Enter fullscreen mode Exit fullscreen mode

Example 2:

myFun(){
    echo "--------"
    echo "Welcome"
    echo "--------"
}

# Calling Function
myFun
Enter fullscreen mode Exit fullscreen mode

Example 2: With arguments

#!/bin/bash
myFun(){
    local num1=$1 # $1-> First argument: 5
    local num2=$2 # $2-> Second argument: 2
    let result=$num1+$num2 
    echo "--------"
    echo "Sum: $result"
    echo "--------"
}

# Calling Function
myFun 5 2
Enter fullscreen mode Exit fullscreen mode

Example 2: Send arguments while executing file

./file.sh arbab anjum

file.sh:

echo $1 # result: arbab
echo $@ # result: arbab anjum -> $@ means all arguments
echo $# # result: 2 -> number of arguments

Enter fullscreen mode Exit fullscreen mode

Useful Concept

  • break - To stop the loop
  • continue - To stop current iteration of loop and start from the next iteration
  • sleep - To create delay between two execution e.g; sleep 1m/1s
  • exit - To stop script to a point. e.g; exit 1
  • $? - exit status - gives you status of previous command if that was successful - status 0 means success
  • basename - strip directory info and only give filename
  • dirname - strip the filename and gives dir path
  • realpath - gives you full path for a file
  • RANDOM - generate random number - echo $RANDOM
  • UID - User ID of the logged in user - echo $UID - UID of root user is 0

Debugging:

Add `set -x` in the script to enable debugging
Enter fullscreen mode Exit fullscreen mode

Scripts:

Check if file exist or not

#!/bin/bash
FILPATH=/home/test/file.csv
if[[ -f $FILEPATH ]]
then
    echo "FILE EXIST"
else
    echo "FILE DON't EXIST"
fi
Enter fullscreen mode Exit fullscreen mode

If you want to exit script when a command fail

set -e # use this
echo "Hello"
cd /root #fail and skip next execution
pwd
Enter fullscreen mode Exit fullscreen mode

Run script in background

nohup ./script.sh
Enter fullscreen mode Exit fullscreen mode

Run Script at specific time using At command

at 12:09 AM # Run and hit enter it will ask what to do 
bash ./script.sh

atq -> to check scheduled job
atrm <id> -> to remove a scheduled job
Enter fullscreen mode Exit fullscreen mode

Crontab - Script automation

crontab -l # view existing cronjobs
crontab -e # Create New

Format:

* * * * * cd /home/arbab/ && ./runfile.sh

Stars from Right To Left
* -> Day of Week (0-6) Sunday=0
* -> month 1-12
* -> Day of month (1-31)
* -> hour 0-23
* -> minute 0-59

https://crontab.guru
Enter fullscreen mode Exit fullscreen mode

Mini Projects

Monitoring free RAM Space

#!/bin/bash
FREE_SPACE=$(free -mt | grep "Total" | awk '{print $4}')
TH=500

if [[ $FREE_SPACE -lt $TH ]]
then
    echo "Normal Memory!"
else
    echo "Running out of memory!"
fi

#--------- Comments ---------
#free -mt -> show total free memory
#grep "Total" -> pick the line containing word total
#awk '{print $4}' print 4th column value
Enter fullscreen mode Exit fullscreen mode

Monitoring free disk Space and send an alert email

#!/bin/bash
FREE_DISK_SPACE=$(df -H | egrep -v "Filesystem|tmpfs" | grep "sda2" | awk '{print $5}' | tr -d %)
TH=90
[email protected]

if [[ $FREE_DISK_SPACE -lt $TH ]]
then
    echo "Disk has enough space!" | mail -s "Disk Space Alert" $TO
else
    echo "Low disk space!"
fi

#--------- Comments ---------
#configure postfix to send emails
#df -h -> show all disk usage
#egrep -v "Filesystem|tmpfs" -> Remove Filsystem and tmps line from output
#grep "sda2" -> search sda2
#awk '{print $5}' print 5th column value
#tr -d % -> truncate/delete % from output
Enter fullscreen mode Exit fullscreen mode

Move files having size more than 20MB to achieve folder

!/bin/bash
# Version: 1
# Date: 19 April 2025

#Variables
BASE=/home/arbab/myFiles
DAYS=10
DEPTH=1
RUN=0

#check if the directory is present or not

if [[ ! -d $BASE ]]
then
    echo "Dir doesn't exist: $BASE"
    exit 1
fi

#create 'archive' folder if not present

if [[ ! -d $BASE/archive ]]
then
    mkdir archive
fi

#Find list of files largest than 20MB

for i in `find $BASE -maxdepth $DEPTH -type f -size +20M`
do
    if [[ $RUN -eq 0 ]]
    then
        echo "[$(date "+%y-%m-%d %H:%M:%S")] archiving $i ==> $BASE/archive"
        gzip $i || exit 1
        mv $i.gz $BASE/archive || exit 1
    fi
done

## ||  runs the command on right side when left side result is false
Enter fullscreen mode Exit fullscreen mode

Automate user account creation

#!/bin/bash

# script should execute with sudo/root access.
if [[ "${UID}" -ne 0 ]]
then
    echo 'Please run with root or sudo user'
    exit 1
fi

# user should provide atleast one argument as username else guide him
if [[ "${#}" -lt 1 ]]
then
    echo 'Usage: ${0} USER_NAME [COMMENT]...'
    exit 1
fi

# ${0} -> Tells the name of script
# store first argument as username

USER_NAME="{$1}"

# All other arguments as comment
shift
COMMENT="{$@}"

# create a password

RANDOM_PASS=$(date +%s%N)
# seconds and nano seconds

# create a user
useradd -c "${COMMENT}" -m $USER_NAME

# -c -> comment
# -m -> Make Dir

# Check if user created successfully or not

if [[ $? -ne 0 ]]
then
    echo "Failed to create user"
    exit 1
fi

# set password for user
echo $PASSWORD | passwd --stdin $USER_NAME

# Check if password is successfully set or not

if [[ $? -ne 0 ]]
then
    echo "Failed to create user"
    exit 1
fi

# force password change on first login
passwd -e $USER_NAME

# Display username password and hostname

echo "Username: $USER_NAME"
echo "Username: $PASSWORD"
echo "Hostname: $(hostname)"

Enter fullscreen mode Exit fullscreen mode

Top comments (0)