Skip to main content

Command Palette

Search for a command to run...

Shell Scripting

Updated
10 min readView as Markdown

Shell helps user to talk with them to kernel because the kernel code is implemented in C language but the user doesn’t know about C language. Hence, they are providing shell commands in the shell layer.

If you want to give many instructions to kernel at a time then you need to write those instructions or commands in one by one line and you need to save the file using .sh extension. The execution of commands from one by one line is called “Shell Script”.

Steven Bourne developed the Shell Script in path /bin/sh. The shell .sh was widely used earlier. But we need some improvements on .sh shell, so we have introduces the improved version called bash (/bin/bash). Bash stands for Bourne Again Shell.

There are different types of shell like csh (Korn Shell), ksh, zsh (Z Shell), fish (Interactive Shell).

How to write Shell Script:-

Create a file

ubuntu@ip-172-31-25-118:~/scripts$ vim scriptfile.sh

Once you create a file then you need to give write permission to yourself (user)

ubuntu@ip-172-31-25-118:~/scripts$ chmod 755 scriptfile.sh

Then you can run the script using 2 ways. One way is you can use “./<filename.sh> and another way is to use “bash filename.sh

Eg 1:

echo "Bilal: Hello Dosto, how are you?" echo "Audience: We are fine"

echo "Bilal: Today what date is it?" date

echo "I was waiting for all of you since" uptime

#echo "Now I am creating a directory" #mkdir ajit

Output: As you know this directory is already exist. If you run this command it will get the output → Initially when I run the command I have created the directory, hence we got this error.

mkdir: cannot create directory ‘ajit’: File exists

echo "There is one more person who will teach you"

User can input using read command. The word name_of_the_person acts as a variable

read name_of_the_person

#You can access the variable using $variable_name

echo "The person name is $name_of_the_person"

#An argument is a input which is given at the time of running a script.

echo "Your first argument will be $1" echo "The total no of arguments is $#"

#What things you have passed in argument

echo "I have passed this many things in argument: $@"

Output:

ubuntu@ip-172-31-25-118:~/scripts$ ./scriptfile.sh john rahul karishma → Here john, rahul and kairshma considered as an arguments

Bilal: Hello Dosto, how are you?

Audience: We are fine

Bilal: Today what date is it?

Sun Sep 15 07:22:37 UTC 2024

I was waiting for all of you since

07:22:37 up 7 min, 1 user, load average: 0.00, 0.00, 0.00

There is one more person who will teach you

sharukh → user will type input

The person name is sharukh

Your first argument will be john

The total no of arguments is 3

I have passed this many things in argument: john rahul karishma

Eg 2: It checks the vote eligibility based on age.

echo "Enter your age"

read age

if [ $age -le 17 ]; then

echo "You are not eligible for vote"

else

echo "Now you can vote"

fi

Output:

ubuntu@ip-172-31-25-118:~/scripts$ ./if_condition.sh

Enter your age

15

You are not eligible for vote

ubuntu@ip-172-31-25-118:~/scripts$ ./if_condition.sh

Enter your age

18

Now you can vote

Eg 3: It checks for a minimum number of arguments and print certain number of arguments.

#!/bin/bash

#Check if there are enough arguments

if [ "$#" -le 4 ]; then

echo "Please provide atleast 5 arguments"

exit 1 #It exit the program

fi

#Loop through arguments from 2nd to 5th array

for i in {2..5}; do

#Print the argument as per position $i echo "Argument $i: ${!i}" → access and print the value of a variable whose name is stored in another variable.

done

Output:

ubuntu@ip-172-31-25-118:~/scripts$ ./for_loop_example.sh 10 20 30 40

Please provide atleast 5 arguments

ubuntu@ip-172-31-25-118:~/scripts$ ./for_loop_example.sh 10 20 30 40 50 Arugement 2: 20

Arugement 3: 30

Arugement 4: 40

Arugement 5: 50

Eg: 4 It prompts the user for input to decide whether to proceed with a certain action.

#!/bin/bash

echo "Do you want to continue (yes/no)"

read user_input

if [ $user_input == "yes" ]; then

echo "You can proceed now"

elif [ $user_input == "no" ]; then

echo "You will not proceed"

else

echo "Default valid input"

fi

Output:

Do you want to continue (yes/no) yes

You can proceed now

ubuntu@ip-172-31-25-118:~/scripts$ ./boolean_condition.sh

Do you want to continue (yes/no) no

You will not proceed

ubuntu@ip-172-31-25-118:~/scripts$ ./boolean_condition.sh

Do you want to continue (yes/no) hbfh

Default valid input

Eg 5: If you want to do same task repeatedly then use for loop

#!/bin/bash

#Creating multi line comments

<< task

Create a custom directory with given range of arguments

task

echo "Enter the root directory"

read root_dir

mkdir $root_dir && cd $root_dir

echo "Enter the custom directory"

read custom_dir

for (( i=$1; i<=$2; i++ )); do

mkdir "${custom_dir}${i}"

done

Output:

ubuntu@ip-172-31-25-118:~/scripts$ ./create_custom_directories.sh 1 6

Enter the root directory

devops

Enter the custom directory

batch

ubuntu@ip-172-31-25-118:~/scripts$ cd devops/

ubuntu@ip-172-31-25-118:~/scripts/devops$ ls

batch1 batch2 batch3 batch4 batch5 batch6

Eg 6: I need to take a backup for my scripts directory and need to store in backup directory which I have created

ubuntu@ip-172-31-25-118:~/scripts$ ls

backup.sh

ubuntu@ip-172-31-25-118:~$ ls

backups

Source Code:

<< comment

This script will take the backup from source to target

comment

src_dir="/home/ubuntu/scripts/"

target_dir="/home/ubuntu/backups"

<< backups

needs to be compress

backups

#gz is an advance zipping mechanism, tar is a utility or a tool for zipping

backup_filename="backup_$(date +%Y-%m-%d-%H-%M-%S).tar.gz"

echo $backup_filename

echo "Backup is started"

echo "Backup will be stored at $backup_filename"

Now we are compressing it

#tar -czvf <dest> <src>

# -c used for compress, -x used to decompress or extract, -v is used to show the information visually, -f specifies the filename, z is used for gunzip

tar -czvf "${target_dir}/${backup_filename}" "$src_dir"

echo "Backup is completed"

Output:

ubuntu@ip-172-31-25-118:~/backups$ ls

backup_2024-09-22-05-37-50.tar.gz

If you want to extract the tar.gz files

ubuntu@ip-172-31-25-118:~/backups$ tar -xzvf backup_2024-09-22-05-37-50.tar.gz

home/ubuntu/scripts/ home/ubuntu/scripts/backup.sh home/ubuntu/scripts/create_custom_directories.sh home/ubuntu/scripts/for_loop_example.sh home/ubuntu/scripts/.backup.sh.swp home/ubuntu/scripts/devops/ home/ubuntu/scripts/devops/batch3/ home/ubuntu/scripts/devops/batch2/ home/ubuntu/scripts/devops/batch1/ home/ubuntu/scripts/devops/batch4/ home/ubuntu/scripts/devops/batch6/ home/ubuntu/scripts/devops/batch5/ home/ubuntu/scripts/boolean_condition.sh home/ubuntu/scripts/scriptfile.sh home/ubuntu/scripts/.backup.sh.swo home/ubuntu/scripts/ajit/ home/ubuntu/scripts/if_condition.sh

ubuntu@ip-172-31-25-118:~/backups$ ls

backup_2024-09-22-05-37-50.tar.gz home

Eg 7: I don’t want to run the script manually. I need to run it automatically in a scheduled time. Then we will use CRON. CRON is known as scheduled task.

I want to run the script in every hour. I’ll edit the crontab file of that script. Inside crontab, there will be a cron jobs.

ubuntu@ip-172-31-25-118:~/backups$ crontab -e

You can open a file using vim editor

ubuntu@ip-172-31-25-118:~/backups$ crontab -e

no crontab for ubuntu - using an empty one

Select an editor. To change later, run 'select-editor'.

  1. /bin/nano <---- easiest

  2. /usr/bin/vim.basic

  3. /usr/bin/vim.tiny

  4. /bin/ed

Choose 1-4 [1]: 2

At every 2nd minute I want to take a backup

Search “cron guru” in google

Add this line in crontab file

/2 * bash /hbackup.shome/ubuntu/scripts/

It refreshes every 2 seconds which runs by ls command

ubuntu@ip-172-31-25-118:~/backups$ watch -n 2 ls

Functions:-

Eg:

check_even_odd () { → Creation of Function

echo "Enter number"

read number

if [ $(($number%2)) -eq 0 ];

then

echo "$number is even"

else

echo "$number is odd"

fi

}

check_even_odd → Function Calling

Output:

ubuntu@ip-172-31-25-118:~/scripts$ ./even_odd.sh Enter number

7

7 is odd

ubuntu@ip-172-31-25-118:~/scripts$ ./even_odd.sh Enter number

8

8 is even

Eg 8: Create the users and display their user name

Code:

#Define the users to be created

users=("Asad" "Gulnaz")

#user is a variable that hold the current value of item in the iteration

#$users[@] refers to elemenets of the arrray having it's own variable named users. for user in "${users[@]}"; do

#Check whether user is already there in system

#The id command is used to get the information about the user like it's user ID, group ID and at which group they belongs

#&>/dev/null is a special file that discards all the output of id command

if id "$user" &>/dev/null; then

echo "User $user is already exist"

else

sudo useradd "$user"

echo "Created user: $user"

fi

done

#Now list the created users

echo "Current users" cut -d':' -f1 /etc/passwd | grep -E 'Asad|Gulnaz'

Output:

ubuntu@ip-172-31-25-118:~/scripts$ ./user_management.sh

Created user: Asad

Created user: Gulnaz

Current users Asad

Gulnaz

If I run the same code again, then here is the output

User Asad is already exist

User Gulnaz is already exist

Current users

Asad

Gulnaz

Eg 9: Create a script that changes the permissions of multiple files in a directory

ubuntu@ip-172-31-25-118:~/qa_configs$ ll

-rw-rw-r-- 1 root ubuntu 0 Oct 14 07:25 demo.txt

Code:

#!/bin/bash

echo "Enter the directory path"

read dir_path

echo "Enter the permissions (eg, 755)"

read permissions

sudo chmod -R $permissions $dir_path → -R stands for recursive

echo "Permissions changed successfully"

Output:-

Enter the directory path

/home/ubuntu/qa_configs

Enter the permissions (eg, 755)

700

Permissions changed successfully

-rwx------ 1 root ubuntu 0 Oct 14 07:25 demo.txt*

Eg 10: Create a script with comments explaining what the script does.

#!/bin/bash

#Prints the current date and time

echo "The current date and time is: $(date)"

#Prints a welcome message

echo "Welcome to the Shell Scripting Challenge"

#End of script

Output:

The current date and time is: Wed Oct 16 14:27:38 UTC 2024

Welcome to the Shell Scripting Challenge

Eg 11: Create a script that declares the variables and assign the values to them.

name="Bilal DevOps Student"

course="DevOps"

echo "My name is $name and I am participating in the $course challenge"

Output:

My name is Bilal DevOps Student and I am participating in the DevOps challenge

Eg 12: Add two numbers and display their sum

num1=5

num2=15

sum=$((num1+num2))

echo "The sum of $num1 and $num2 is $sum."

Output: The sum of 5 and 15 is 20.

Eg 13: Define three built in variables that display the relevant information.

echo "Current logged-in user: $USER"

echo "Home directory: $HOME"

echo "Current shell: $SHELL"

Output:

Current logged-in user: ubuntu

Home directory: /home/ubuntu

Current shell: /bin/bash

Eg 14: Create a directory if the command is successful, else it prints an error message.

#!/bin/bash

DIR="/root/day11/task1"

#Check if the directory exist. -d is a test operator used in shell scripting to check if a directory exist.

if [ -d "$DIR" ]; then

echo "Directory $DIR already exists"

else

#Attempt to create a directory

sudo mkdir -p $DIR

#Check exit status. $? -> define the status of last command failed. In this case, it checks the mkdir command

if [ $? -ne 0 ]; then

echo "Failed to create a directory $DIR"

else

echo "Directory $DIR created successfully"

fi

fi

Output:

ubuntu@ip-172-31-25-118:~/scripts/error_handling$ sudo ./check_exit_status.sh Directory /root/day11/task1 created successfully

If I run the same script again

ubuntu@ip-172-31-25-118:~/scripts/error_handling$ sudo ./check_exit_status.sh Directory /root/day11/task1 already exists

Eg 15: Now I have modified the code. I have created a file inside the parent directory.

#!/bin/bash

DIR="/root/day11/task1"

FILE="$DIR/myfile.txt"

#Check if the directory exist. -d is a test operator used in shell scripting to check if a directory exist.

if [ -d "$DIR" ]; then

echo "Directory $DIR already exists"

else

#Attempt to create a directory

sudo mkdir -p $DIR

#Check exit staus. $? -> define the status of last command failed. In this case, it checks the mkdir command

if [ $? -ne 0 ]; then echo "Failed to create a directory $DIR"

else

echo "Directory $DIR created successfully"

fi

fi

#Check if the file exist

if [ -f "$FILE" ]; then

echo "$FILE already exists"

else

echo "Creating file $FILE.."

#Create the file

sudo touch "$FILE"

#Check the exit status of the touch command

if [ $? -ne 0 ]; then

echo "Failed to create file $FILE"

else

echo "File $FILE created successfully"

fi

fi

This is my first output

ubuntu@ip-172-31-25-118:~/scripts/error_handling$ sudo ./check_exit_status.sh Directory /root/day11/task1 already exists Creating file /root/day11/task1/myfile.txt.. File /root/day11/task1/myfile.txt created successfully

When I run same script again

ubuntu@ip-172-31-25-118:~/scripts/error_handling$ sudo ./check_exit_status.sh Directory /root/day11/task1 already exists

/root/day11/task1/myfile.txt already exists

Eg 16: Create a temp file and set a trap to delete the file

Create a directory inside /root/task3

#!/bin/bash

#Create a temp file

temp_file="/root/task3/tempfile_$$.txt"

touch "$temp_file"

echo "Temporary file created at $temp_file";

echo "Script is running"

#Script automatically creates temporary file for 10 seconds

sleep 10

#Normal exit

echo "Script completed succesfully"

#Set up a trap to delete the temporary file on exit

trap 'echo "Deleting temporary file"; rm -f "$temp_file"' EXIT

Output:

ubuntu@ip-172-31-25-118:~/scripts/error_handling$ sudo bash delete_temp_file.sh

Temporary file created at /root/task3/tempfile_5035.txt

Script is running

Script completed succesfully

Deleting temporary file

The trap command is used to specify the command when the shell receives the certain signal or when certain events get occurred.

Eg 17: Write a script that reads a non-existent file and redirects the error message to a file called error.log

#!/bin/bash

#Attempt to read a non-existent file

#This command read a file called non_existent_file.txt, which does not exist.

# 2> error.log -> This redirects to a standard error to a file name called error.log. If the file does not exist, it will create it.

cat non_existent_file 2> error.log

#Notify user -> Informs the user that error message has redirected.

echo "Error messages redirected to error.log"

Output:

ubuntu@ip-172-31-25-118:~/scripts/error_handling$ ./redirecting_errors.sh

Error messages redirected to error.log

ubuntu@ip-172-31-25-118:~/scripts/error_handling$ cat error.log

cat: non_existent_file: No such file or directory

18 views

More from this blog

Untitled Publication

36 posts