0% found this document useful (0 votes)
10 views

Ch6_Linux Bash ‎Shell

Uploaded by

mody.20.fa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Ch6_Linux Bash ‎Shell

Uploaded by

mody.20.fa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

IOS203_Ch6

Chapter 6: Linux Bash Shell

Using Shell Variables ................................................................................. 3


Shell Scripting Language.............................................................................. 9

1
IOS203_Ch6

Objectives
Upon completion of this unit, you should be able to:

 Configure your working environment using variables and shell startup files;
 Create functions and aliases;
 Write, execute and debug scripts using shell-scripting language.

Keywords
Shell variables, shell functions, env, set, #!, PATH, alias, unalias, shift, read, test, &&, ||,
case, for, while, if ... then ... else … fi, until, /etc/profile, ~/.bash_profile, ~/.bash_login,
~/.profile, ~/.bash_logout, ~/.bashrc, /etc/bashrc, /etc/profile.d.

2
IOS203_Ch6

CentOS and most Linux systems use the bash shell by default; the bash shell is a program that
interprets user commands, which are either directly entered by the user, or which can be read
from a file called the shell script or shell program. Shell scripts are, not compiled but interpreted.
They are read by the shell line per line and the shell searches for those commands on the system
in order to pass them to the kernel. The kernel executes the commands and returns the results to
the shell which may display them on the terminal window. Another important task of the bash
shell is to provide a user environment, which can be configured individually using shell variables
stored in configuration files.

1. Using Shell Variables

A variable is a label that has a value resident in memory and can be hold by a file stored on a hard
disk. It can be used in commands, shell scripts and applications. Shell variables are case sensitive
and must prefixed by the dollar sign ‘$’ when using their values. There are two types of shell
variables: local and environment. While local variables are used by the shell in which they are
created, the environment variables are inherited by child shells such as when a new shell is
launched after logging in using the bash command.

The following example shows you how to set and use a local variable:

When setting a variable, don’t add any spaces on either side of the ‘=’ sign. When executing the
echo $A command, the shell looks for a variable named like the string following the dollar sign and
replaces it with the value of the variable, or with nothing if the variable does not exist. In the
previous example, the shell replaces $A by 250 which is the variable value.

The bash shell replaces variables with their values in double quoted lines, but not in single quoted
lines:

The following table contains some common variables of the bash shell. While some variables are
initialized by the bash shell and can be reassigned by the user, other variables are read only, and
may not be set by the user (e.g., last six variables in the table).

Variable Description
PWD Current working directory
RANDOM Random number between 0 and 32767
SECONDS Number of seconds since the shell was started
BASH_VERSION Current bash version

3
IOS203_Ch6

HOSTNAME DNS hostname of the current machine


OLDPWD Previous working directory

SHELL Path to the current shell

HOME Path to the user home directory


Location of your mailbox file. The file is typically your username in
MAIL
the /var/spool/mail directory.
Location of your history file. It is typically located at
HISTFILE
$HOME/.bash_history
Number of history entries that can be stored. After this number is
HISTFILESIZE reached, the oldest commands are discarded. The default value is
1,000
HISTCMD Number of the current command in the history list
The colon-separated list of directories used to find commands that
you type. The default value for regular users is:
PATH /usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/home/timothy/bin.
For the root user, the value also includes /sbin, /usr/sbin, and
/usr/local/sbin.
Number of shell levels associated with the current shell session.
When you log in to the shell, the SHLVL is 1. Each time you start a
SHLVL
new bash command (e.g., by using su to become a new user, or by
simply typing bash), this number is incremented
PS1 The default prompt in bash.

TERM The current terminal type (for example, xterm)


The display used by X window system. This variable is usually set
DISPLAY
to :0.0, which means the first display on the current computer
? The exit status of the most recently executed command

$ Process id (pid) of current shell

_ Last token of the previous command

PPID The process id (pid) of the shell's parent.

UID The userid of the current user

Here are the values of some variables of the bash shell on my Centos Linux:

4
IOS203_Ch6

set command

This command, without arguments, lists both shell local variables and environment variables
associated with the shell. You can use set | less command line to see the shell variables as follows
in the example below (the result of the command is truncated):

Linux allows users to use the bash shell to create or modify an environment variable, and then all
commands started by the shell will inherit that variable. You can transform a shell variable into
an environment variable by using the export command.

env command

This command, without arguments, lists only variables which have been exported to the
environment. Here is an example of some environment variables shown as a result of executing
the env command:

5
IOS203_Ch6

The example below shows you how to export a bash variable to make it an environment variable:

PATH variable

This variable determines where the shell is looking for commands to execute; it contains a list of
directories, separated by colons.

Not all of the executable files are stored in directories that are listed by your PATH environment
variable. Just because a program resides outside of your path, it does not mean that you cannot
run it. However, you must specify the program using the absolute path to that program.

If you want the shell to look in the Shell_lang directory, then add “:/home/student/Shell_lang” at
the end of your PATH value as follows:

Now, you can run any script stored in that directory without need to use the absolute path to the
script.

Function definition

A function is a group of commands that are assigned a name. To execute this group of commands,
you simply call the function by its name as any other command. In the following example, we
define a function named Hello. When you call the function using its name, it writes a hello
message and then prints the date and time on the screen:

If you exit the session, and login again, you will get a message telling you that “Hello” is not found
when trying to execute the Hello function:

6
IOS203_Ch6

When you define a variable (or a function), it will reside in memory during the current session.
When logging out the session, the variable (or function) will be deleted. In order to make your
variables (or functions) available for next sessions, you should store them in files on the hard disk.

Aliases

Alias is like custom shortcut used to represent a command (or a set of commands) executed with
or without options. The ls command, for example, is not else than an alias.

The alias command shows on the screen a list of defined aliases on your profile:

You can use the alias command to create myls alias as follows:

$ alias myls=’ ls –lah ‘

The unalias command is used to remove entries from the current user's list of aliases:

7
IOS203_Ch6

Shell startup files

After invoking the bash shell, shell startup files (also called shell-initializing files) are read. What
files are read depends upon whether the shell is invoked as an interactive or non-interactive [1].
While interactive shell is a shell that reads and writes to a user’s terminal, non-interactive shell is
a shell that is not associated with a terminal, like when executing a script. An interactive could be
login or non-login shell. An interactive login shell is invoked when a user login to the terminal
either remotely via ssh or locally, or when bash is launched with the --login option. An interactive
non-login shell is invoked from the login shell, such as when typing bash in the shell prompt or
when opening a new terminal tab on the GUI.

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --
login option, it first reads and executes commands from the /etc/profile file, if that file exists.
After reading default global settings stored in the /etc/profile file, the bash shell looks in the user
home directory for ~/.bash_profile, ~/.bash_login, and ~/.profile files, in that order, and reads
and executes commands from the first readable file found.

 The /etc/profile login shell file: it contains values of shell variables specifying all settings
of all users' environments such as: PATH, USER, MAIL, HOSTNAME, HISTSIZE and the
umask value. It contains settings of some other startup programs. It will also run the
scripts found in the /etc/profile.d directory.

 The ~/.bash_profile login shell file: in this file, you can add individually extra configuration
options or change default settings:

 The ~/.bash_login login shell file: this file contains specific settings that are normally only
executed in the absence of ~/.bash_profile.

 The ~/.profile login shell file: in the absence of ~/.bash_profile and ~/.bash_login,
~/.profile is read. It can hold configurations similar to their contents. The ~/.profile file is
read by all shells, while ~/.bash_profile only by the bash shell.

8
IOS203_Ch6

 The ~/.bash_logout: this is an individual login shell file; it contains specific instructions
executed automatically when a login shell exits. For example, it is useful if you want to
make backup of your files just before logging out.

 The ~/.bashrc non-login shell file: you can use it to add individually extra configuration
options or change default global settings. You can add your private shell functions and
aliases.

 The /etc/bashrc non-login shell file: it contains system-wide definitions for shell functions
and aliases. When the bash is invoked as an interactive non-login shell, it reads and
executes commands from this file if the file exists, and it is readable.

 The /etc/profile.d directory: all readable scripts stored in this directory are read and
executed at startup; they do things like enabling color-ls, aliasing vi to vim, setting locales,
etc.

Login shells first call /etc/profile, which calls /etc/profile.d. Then, the file ~/.bash_profile is
called. This file, in turn, calls ~/.bashrc, which calls /etc/bashrc. Each script in turn can undo
changes made in previously called scripts.

Non-login shells first call ~/.bashrc. This calls /etc/bashrc, which calls /etc/profile.d.

Note: If any of the previous files does not found, you can create it.

Shell Scripting Language


Everything that you can call from the CLI, you can also call it from a shell script. You would never
get any work done if you typed every command on your Linux system. It is better to group
together commands that you run all the time in shell scripts.

A shell script is series of commands, functions or variables written in a text file, which could be
edited using text editors. It is just like batch files in MS-DOS, but more powerful and interpreted,

9
IOS203_Ch6

line-by-line, in the same way that you write the lines, one-by-one, in interactive shell. Then, that
file can be run as a command.

Shell scripts are useful for the following purposes:


 Automating commonly used commands;
 Performing system administration;
 Troubleshooting;
 Creating simple applications;
 Creating and modifying files;
 …

Creating and executing shell scripts

The first line in a shell script should identify the shell that’s used to interpret and run it, such as
the following:

#!/bin/bash

Shell scripting language uses the hash mark # as a comment character, so the script interpreter
ignores the words following this mark. The first two characters of a shell script #! are called “she-
bang” or magic number (sometimes called “sha-bang”) and cannot be a comment. In our example,
/bin/bash points to the bash shell, but you can use another shell, such as /bin/sh, /bin/tcsh or
/usr/bin/perl (used for Perl scripts).

After writing the shell script using a text editor (e.g., vi), you should modify its permissions to
make it executable. You do this with the chmod command as follows:

[student@StudentHost ~]$ chmod u+x myscript.sh

where myscript.sh is the script name.

Then, you can type the script name preceded by ./ to tell the system to run the script in the current
directory.

You can also run the script by typing the shell name (i.e., bash) followed by the script name as:

[student@StudentHost ~]$ bash myscript.sh

When you need to run the script regularly, you can move it to a directory whose path exist in the
value of the PATH variable, such as /usr/local/bin. Thus, you can just type myscript.sh.

We can write a bash script that can accept arguments from the CLI as follows:.

[student@StudentHost ~]$ bash myscript.sh "arg1" "arg2"..."argN"

To access these arguments, we can use the positional parameters ($1 to $9) in the script. Each
parameter corresponds to the position of the argument on the command line.

10
IOS203_Ch6

The first argument is read by the shell into the parameter $1, the second argument into $2, and
so on. After $9, you must enclose the arguments in brackets like ${10}, ${11}, and ${12}. The
following table contains common command line arguments:

$0 contains shell script name


$n contains the nth argument, n =1,2,3 …
$# gives count of all arguments
$* lists all arguments (sometimes, you could use $@)

shift command
In some shells, you cannot use brackets like ${10}. Therefore, to access parameters with numbers
greater than 9, you should use the shift command. In this case, $1 will be lost, $2 becomes $1, $3
becomes $2, and so on. The inaccessible 10th parameter becomes $9 and becomes accessible.

Debugging shell scripts


Linux shells provide a debugging mode to determine what causes the script to fail; they allow you
to display each command and its arguments as they are executed.

In order to debug your shell script, write set –x after the shebang line as follows:

#!/bin/bash
set –x # activate debugging from here

An alternative way to do the same thing is to write –x at the end of the shebang line:

#!/bin/bash –x # activate debugging from here

You could also launch your scripts using the bash command with –x option:

[student@StudentHost ~]$ bash –x script.sh

When executing your script using debugging mode, each command will be preceded by a plus sign
‘+’.

You could write the set +x command to disable the debugging as follows:

[student@StudentHost ~]$ set +x # stop debugging from here

You could, also, put set +x at the end of your script to disable the debugging mode.

Here is a shell script that helps you to understand the input arguments and the debugging mode:

#!/bin/bash
set -x
echo "your script is $0"
echo "hi $2"
echo "$#"
echo "$*"

11
IOS203_Ch6

echo "$@"
shift
echo "hi $2"
echo "$?"
echo "hi $2"
set +x

The output of this script is:

read command
This command asks for the user’s input and puts it in a variable. Here is a shell script showing you
how to use the read command:

#!/bin/bash
read -p "Enter a name: " name
echo "Hello $name"
echo "-----------------"

The output of this script is:

The option –p is used to display “Enter a name” to user, without a newline, before beginning to
read.

12
IOS203_Ch6

test command
This command test whether something is true or false. Here is an example showing how to use
the test command to testing whether 5 is greater than 22.

The test command returns 1 if the test fails, it returns 0 when a test succeeds.

&& control operator

This operator is used to chain commands together, such that the next syntax:

$ command1 && command2

command2 is run if and only if the command1 exited without errors. More accurately, command1
exits with a return code of 0 (i.e., true).

|| control operator

This operator is used to chain commands together, such that the next syntax:

$ command1 || command2

command2 is run if and only if the command1 exited with errors. More accurately, exits with a
return code that does not equals to 0 (i.e., false).

You can replace the test command by square brackets. In the following examples, the first two
command lines are equivalent to the last two command lines.

String comparison
The following table shows you most common string comparisons:

Logical Statement Returns True (0) if


[ string1 = string2 ] string1 equals string2
[ string1 != string2 ] string1 does not equal string2
[ string1 < string2 ] string1 precedes string2 in lexical (alphabetical) order
[ string1 > string2 ] string1 follows string2 in lexical (alphabetical) order
[ -z string1 ] string1 has length zero (holds null value)

13
IOS203_Ch6

[ -n string1 ] string1 has non zero length (contains one or more characters)

Here are some examples:

Numerical comparison
The following table shows you most common numerical comparisons:

Numerical Statement Returns True (0) if


[ $number1 -eq $number2 ] number1 equals number2
[ $number1 -ne $number2 ] number1 does not equal number2
[ $number1 -lt $number2 ] number1 is less than number2
[ $number1 -gt $number2 ] number1 is greater than number2
[ $number1 -le $number2 ] number1 is less than or equal to number2
[ $number1 -ge $number2 ] number1 is greater than or equal to number2

Here are some examples:

File operators
The following table shows you most common file operators:

Operator Description
-a filename True if the file exists
-b filename True if the file exists and is a block special file (e.g.,/dev/sda or /dev/sda1)
-c filename True if the file exists and is a character special file (e.g.,/dev/tty1)

14
IOS203_Ch6

-d filename True if the file exists and is a directory


-e filename True if the file exists; this is the same as -a
True if the file exists and is a regular file, as opposed to a directory, a
-f filename
device special file, or a link, among others
-h filename True if the file exists and is a symbolic link
-k filename True if the file exists and its "sticky'" bit is set
-s filename True if the file exists and has a size greater than zero
-u filename True if the file exists and its set-user-id bit is set
-w filename True if the file exists and is writable
-x filename True if the file exists and is executable
-L filename True if the file exists and is a symbolic link
-N filename True if the file exists and has been modified since it was last read
-O filename True if the file exists and is owned by the effective user ID
True if file1 is newer (according to modification date) than file2, or if file1
file1 -nt file2
exists and file2 does not
file1 -ot file2 True if file1 is older than file2, or if file2 exists and file1 does not

Here are some examples:

Boolean operators
The following table shows you most common boolean operators:

Operator Description
! This is logical negation. This inverts a true condition into false and vice versa.
-o This is logical OR. If one of the operands is true, then the condition becomes true.
This is logical AND. If both the operands are true, then the condition becomes true
-a
otherwise false.

if ... then ... else … fi statement


This statement is about choice; it has the following syntax:

if [ condition ]; then
block_of_statements1
else
block_of_statements2
fi

If the condition succeeds, then the block_of_statements1 is executed. Else, block_of_statements2


is executed. The if statement must end with fi to represent the end of the statement.

15
IOS203_Ch6

Note: The part “else block_of_statements2” is optional.

Here is a shell script showing you how to use the if conditional statement:

#!/bin/bash
if [ $# -ne 2 ]; then
echo "you must supply two arguments (strings)"
elif test $1 = $2
then
echo "The strings are matched"
else
echo "The strings are not matched"
fi

The output of this script is:

Note: In this script, a nested if statement (i.e., if ... then ... elif … then … fi) is used. You can add
many elif command statements before the final else statement. You should follow each elif by a
then statement.

case statement
This statement is similar to switch statement in C programming language. It can be used instead
of nested if statements to simplify complex conditionals when you have multiple different
choices; it has the following syntax:

case expression in

pattern_1)
block_of_statements1
;;
pattern _2)
block_of_statements2

16
IOS203_Ch6

;;
pattern _N)
block_of_statementsN
;;
*)
block_of_statements_Default
;;
esac

where the commands in the block_of_statements1 for the first match are executed, the
commands in the block_of_statements2 for the second match are executed, the commands in
the block_of_statementsN for the N match are executed. The commands in
the block_of_statements_Default are executed when no one of the previous blocks is executed.

The '|’ symbol can be used for separating multiple patterns, and the ‘)’ operator terminates a
pattern list. Each case plus its according commands are called a clause. Each clause must be
terminated with ‘;;’. Each case statement is ended with the esac word.

Here is a shell script showing you how to use the case conditional statement:

#!/bin/bash
echo -e "\n Command Menue \n"
echo "---------------"
echo "a. Current date and time"
echo "b. Users currently logged in"
echo "c. Name of the working directory"
echo -e "[0-9]. sleep for [0-9] seconds\n"
echo -e "Enter a,b, c or any digit: \c"
read answer
case "$answer" in
a)
date
;;
b)
who
;;
c)
pwd
;;
[0-9])
sleep $answer
;;
*)
echo "There is no selection: $answer"
esac

17
IOS203_Ch6

The output of this script is:

for loop

In the bash shell, the classical for loop has three syntaxes; we use them in the following script:

#!/bin/bash
for i in 1 2 3 #This is the first syntax
do
echo "Welcome $i time"
done
sleep 2
for ((i = 0 ; i <= 4 ; i++)) #This is the second syntax
do
echo "Welcome $i time"
done
echo "----------"
echo "break and continue"
for index in 1 2 3 4 5 6 7 #This is the third syntax
do
if [ $index -le 3 ]; then
echo "continue"
continue
fi
echo "$index"
if [ $index -ge 3 ]; then
echo "break"
break
fi
done
echo "The End"

The output of this script is:

18
IOS203_Ch6

Note: In the previous script, beak and continue are used. Those statements are used to stop a
loop or skip some of its iterations. The break statement is used to terminate the execution of the
entire loop. The continue statement is similar to the break command, except that it causes the
current iteration of the loop to exit, rather than the entire loop.

while loop

The while loop is used to execute a set of commands while some condition is true. Below a simple
script showing you how to use the while loop:

#!/bin/bash
tries=0
limits=5
input="hi"
while [ "$input" != "secret" ] && [ $tries -lt $limits ]
do
echo "Enter your passwd"
read input
tries=$(( $tries + 1))
done
if [ $input = "secret" ]
then echo "welcome"
else
echo "retry, limit $limits is reached"
fi

19
IOS203_Ch6

The output of this script is:

until loop

This loop is used when you need to execute a set of commands until a condition is true. Below a
simple script showing you how to use the until loop:

#!/bin/bash
secretname=jenny
name=noname
until [ $name = $secretname ]
do
echo -e "your guess: \c"
read name
done

The output of this script is:

Using functions

Below a simple script showing you how to define and use a function within a script:

#!/bin/bash
func() {
echo "date function";
date;
}
echo "this is first call"
func
sleep 3
echo "this is second call"
func

20
IOS203_Ch6

The output of this script is:

Arithmetic within a script

Below a simple script showing you how to define and use a function within a script:

#!/bin/bash
calsum() {
echo `expr $1 + $2`
}
z=`calsum $1 $2`
echo $z

The output of this script is:

Note: There must be spaces between the operators and the expressions. For example, 1+8 is not
correct; it should be written as 1 + 8.

21
IOS203_Ch6

Questions
1- What must the first word of the first line in an executable bash script?
a. ##bash
b. #!bash
c. !!/bin/bash
d. shebang /bin/bash
e. None of the above
2- What permission(s) must a user have in order to execute a shell script?
a. execute permission
b. write permission
c. read permission
d. a and c
e. All of the above
3- Write a shell script that asks for a filename. Verify existence of the file, then verify that you
own the file, and whether it is writable. If not, make it writable.
4- Write a shell script to count down from 10 to 1, and print the result on the screen
5- Write a shell script to count from 1 to 15, and print the result on the screen
6- Write a shell script that uses a while loop to count from 2 to 12.
7- Create a new user account as your SVU account, ex. abc_88888, and login with it to a machine
that has its host name like the username you created. (you should show how you changed the
hostname in your answer). When you login, you should have on the screen:
a. A welcome message like this: “Welcome abc_88888, today is ##-##-2020 at hh:mm”.
You should replace abc_88888 by your username and “##-##-2020 at hh:mm” by the
current date and time.
b. Your user information: your UID number and your login shell. Besides the previous
requirements, you should resize the console screen to 25x80 (25 lines and 80
columns).
8- Write a shell script that prints on the screen a welcome message. The message should contain
the statement “Good TIME Abc_88888”, where the word “TIME” should be replaced with
“morning”, “afternoon”, “evening” or “night” according to the system time (Morning hours
belong to [05 – 12[, afternoon hours belong to [21 – 17[, evening hours belong to [17 – 20[,
and night hours belong to [20 – 05[).
9- Write a shell script that adds the extension “.svu” to all the files stored in a given directory.
10- Write a shell script to read a number and print it in reverse order. If the number is missed, the
script displays an error message.
11- Write a shell script that will print the number of files and directories in the current directory.
It should not count files and directories whose names begin with a dot (“.”). The script should
just print a single number.
12- Give the code for a bash script that deletes files containing more than a given number of
bytes. Suppose that the script arguments are named sz, f1, f2, f3, ..., fn. Argument sz is the
size (number of bytes) and arguments f1 through fn are the file names. The script should
behave as follows:
a. If no arguments are given (i.e., sz is missing,) the script should write an error message
to stderr and exit with a non‐zero exit status.
b. If at least the first argument (sz) is present, the script should process each of the file
arguments f1 through fn in turn. For each file argument,

22
IOS203_Ch6

i. If the file does not exist or is not a regular file, then ignore that argument and
continue processing with the next file argument. Do not show any messages.
ii. If the file does exist and is a regular file (i.e., not a directory or some other
kind of special file), then if it contains more than sz bytes it should be deleted.
iii. If there are no file arguments (i.e., only sz is present), the script should
terminate without doing anything further.
Hint: wc –c, bash test condition -f.
13- Suppose we have a long text file named story.txt. Write a shell script that will print out to the
screen the first 5 lines and the last 3 lines of the story.txt file.
14- Write a shell script to validate password strength. Here are a few assumptions for the
password string.
a. Length – minimum of 8 characters.
b. Contain both alphabet and number.
c. Include both the small and capital case letters. If the password doesn’t comply with
any of the above conditions, then the script should report it as a “Weak Password”.
15- Write a script that receives four parameters(file names), and does the following tasks:
a. Output the four parameters in reverse order;
b. Check whether those files exist or not.
16- Write a script, using case statement, to perform basic Math operations such as:
 + addition
 - subtraction
 x multiplication
 / division
The name of the script must be “MathScript” which works as follows:
$ ./ MathScript 16 / 4
Check for correct arguments
17- Improve the previous script “MathScript” to test that the numbers are between 1 and 100,
exit with an error if necessary.
18- Improve the previous script “MathScript” to congratulate the user if the sum equals the
product.
19- Write a shell script that counts the number of files ending in .txt in the current directory.
20- Write a script to print on the screen the content of a given file from a given line number to a
next given number of lines. e.g., if we call this script “ContentScript” and run it as follows:
$ ContentScript 3 12 myf
The output should be the content of “myf” file from line 3 to line 14.

23
IOS203_Ch6

References
[1] https://linuxize.com/post/bashrc-vs-bash-profile/

[2] Red Hat Linux Essentials RH033-RHEL5-en-2-20070306


[3] Paul Cobbaut, “Linux Fundamentals”, https://linux-training.be/funhtml/index.html. Updated
on 2015-05-24

24

You might also like