Saturday 8 March 2014

A Quick Guide To Unix Shell Scripting

1) what is shell script ?

Normally shells are interactive. It means shell accept command from you (via keyboard) and execute them. But if you use command one by one (sequence of 'n' number of commands) , the you can store this sequence of command to text file and tell the shell to execute this text file instead of entering the commands. This is know as shell script.
Shell script defined as:

"Shell Script is series of command written in plain text file. Shell script is just like batch file is MS-DOS but have more power than the MS-DOS batch file."

2)  Shebang:

Naturally, a shell script should start with a line such as the following:
#!/bin/bash
This indicates that the script should be run in the bash shell regardless of which interactive shell the user has chosen. This is very important, since the syntax of different shells can vary greatly.

3) How to write shell script ?

Now i will walk you through  how to write shell script,execute them etc.We will getting started with writing small shell script, that will print "Hello UnixMantra" on screen. Before starting with this you should know.
Following steps are required to write shell script:
(1) Use any editor like vi or exedit to write shell script.

(2) After writing shell script set execute permission for your script as follows

syntax: chmod permission your-script-name

Examples:
$ chmod +x your-script-name
$ chmod 755 your-script-name

Note: This will set read write execute(7) permission for owner, for group and other permission is read and execute only(5).

(3) Execute your script as

syntax: bash your-script-name
sh your-script-name
./your-script-name

Examples:
$ bash bar
$ sh bar
$ ./bar

NOTE: In the last syntax ./ means current directory, But only . (dot) means execute given command file in current shell without starting the new copy of shell, The syntax for . (dot) command is as follows

Syntax: . command-name

Example:
$ . foo

Now you are ready to write first shell script that will print "Hello UnixMantra" on screen. See the common vi command list , if you are new to vi.

$ vi firstscript
#
# My first shell script
#
clear
echo "Hello UnixMantra"

After saving the above script, you can run the script as follows:
$ ./firstscript

This will not run script since we have not set execute permission for our script first; to do this type command

$ chmod 755 firstscript
$ ./firstscript

4) Commenting Commands:

Any line beginning with a hash '#' character in the first column is taken to be a comment and is ignored. The only exception is the first line (shebang #!/bin/sh)  in the file, where the comment is used to indicate which shell should be used.

5) Shell Variables:

Like every programming language, shells support variables. Shell variables may be assigned values, manipulated, and used. Some variables are automatically assigned for use by the shell.
there are two types of variable:

(1) System variables - Created and maintained by Unix OS itself. This type of variable defined in CAPITAL LETTERS.
(2) User defined variables (UDV) - Created and maintained by user. This type of variable defined in lower letters.
Any programming language needs variables. You define a variable as follows:
Y="hello"
and refer to it as follows:
$Y
More specifically, $Y is used to denote the value of the variable Y.

$ no=10
# this is ok
$ 10=no
# Error, NOT Ok, Value must be on right side of = sign.

To define variable called 'vech' having value car
$ vech=car

To define variable called n having value 10
$ n=10
Caution: Do not modify System variable this can some time create problems.
Yon can  print the value of the variable or command using  "echo"  or  "print"
#echo "$Y"
hello
I always suggest you to use "curly braces {}" to protect the variables, we have a good advantage when grabbing the actual values of variables.
Eg:
# X=Hello
#echo "$XWorld"
There wont be any output  by above command because the shell looks for "Xworld" as variable rather X.We can avoid this embracing situation using curly braces.
#echo "${X}World"
HelloWorld

6)  Analysing  quotes:

There are three types of quotes

Quotes
Name
Meaning
"
Double Quotes
"Double Quotes" - Anything enclose in double quotes removed meaning of that characters (except \ and $).
'
Single quotes
'Single quotes' - Enclosed in single quotes remains unchanged.
`
Back quote

`Back quote` - To execute command
Eg:
MY_VALUE=Hello
$ echo '$MY_VALUE'
$MY_VALUE
$ echo "$MY_VALUE"
Hello
$ echo "Today is date"
Can't print message with today's date.
$ echo "Today is `date`".
It will print today's date as, Today is  Fri Mar 07 15:35:08 EDT 2014

7)  Conditional Statement:

if or elif
Conditionals are used where an action is appropriate only under certain circumstances. The most frequently used conditional operator is the if-statement. For example, the shell below displays the contents of a file on the screen using cat, but lists the contents of a directory using ls.
#!/bin/sh
# show script
if [ -d $1 ]
then
  ls $1
else
  cat $1
fi
Here, we notice a number of points:

  • The if-statement begins with the keyword if, and ends with the keyword fi (if, reversed).
  • The if keyword is followed by a condition, which is enclosed in square brackets. In this case, the condition -d $1 may be read as: if $1 is a directory.
  • The line after the if keyword contains the keyword then.
  • Optionally, you may include an else keyword.
If the condition is satisfied (in this case, if $1 is a directory) then the commands between the then and else keywords are executed; if the condition isn't satisfied then the commands between the else and fi keywords are executed. If an else keyword isn't included, then the commands between the then and fi keywords are executed if the condition is true; otherwise the whole section is skipped.

Type1
Type2
Type3

if condition

then

    statement1

    statement2
    ..........
fi

if condition
then
    statement1
    statement2
    ..........
else
    statement3
fi

"if condition1
then
    statement1
    statement2
    ..........
elif condition2
then
    statement3
    statement4
    ........   
elif condition3
then
    statement5
    statement6
    ........   
fi

To run simple test

If you wish to specify an alternate action when the condition fails

it is possible to test for another condition if the first "if" fails. Note that any number of elifs can be added.
The Test Command and Operators
The command used in conditionals nearly all the time is the test command. Test returns true or false (more accurately, exits with 0 or non zero status) depending respectively on whether the test is passed or failed. It works like this:
test operand1 operator operand2
for some tests, there need be only one operand (operand2) The test command is typically abbreviated in this form:
[ operand1 operator operand2 ]
To bring this discussion back down to earth, we give a few examples:
#!/bin/bash
X=3
Y=4
empty_string=""
if [ $X -lt $Y ] # is $X less than $Y ? 
then
 echo "\$X=${X}, which is smaller than \$Y=${Y}"
fi

if [ -n "$empty_string" ]; then
 echo "empty string is non_empty"
fi

if [ -e "${HOME}/.surya" ]; then    # test to see if ~/.surya exists
 echo "you have a .surya file"
 if [ -L "${HOME}/.surya" ]; then   # is it a symlink ?  
  echo "it's a symbolic link
 elif [ -f "${HOME}/.surya" ]; then  # is it a regular file ?
  echo "it's a regular file"
 fi
else
 echo "you have no .surya file"
fi
A brief summary of test operators
Here's a quick list of test operators. It's by no means comprehensive, but its likely to be all you'll need to remember (if you need anything else, you can always check the bash manpage ... )

operator produces true if... number of operands
-n operand non zero length 1
-z operand has zero length 1
-d there exists a directory whose name is operand 1
-f there exists a file whose name is operand 1
-eq the operands are integers and they are equal 2
-neq the opposite of -eq 2
= the operands are equal (as strings) 2
!= opposite of = 2
-lt operand1 is strictly less than operand2 (both operands should be integers) 2
-gt operand1 is strictly greater than operand2 (both operands should be integers) 2
-ge operand1 is greater than or equal to operand2 (both operands should be integers) 2
-le operand1 is less than or equal to operand2 (both operands should be integers) 2
Case Statements:
The case construct has the following syntax:
case word in
pattern) list ;;
...esac      
An example of this should make things clearer:
!#/bin/sh
case $1
in
1) echo 'First Choice';;
2) echo 'Second Choice';;
*) echo 'Other Choice';;
esac
"1", "2" and "*" are patterns, word is compared to each pattern and if a match is found the body of the corresponding pattern is executed, we have used "*" to represent everything, since this is checked last we will still catch "1" and "2" because they are checked first. In our example word is "$1", the first parameter, hence if the script is ran with the argument "1" it will output "First Choice", "2" "Second Choice" and anything else "Other Choice". In this example we compared against numbers (essentially still a string comparison however) but the pattern can be more complex, see the SH man page for more information.

8) Looping Commands:

Whereas conditional statements allow programs to make choices about what to do, looping commands support repetition. Many scripts are written precisely because some repetitious processing of many files is required, so looping commands are extremely important.

Loops are constructions that enable one to reiterate a procedure or perform the same procedure on several different items. There are the following kinds of loops available in bash

  • for loops
  • while loops
'For' loops
The syntax for the for loops is best demonstrated by example.
#!/bin/bash
for X in red green blue
do
 echo $X
done
The for loop iterates the loop over the space seperated items. Note that if some of the items have embedded spaces, you need to protect them with quotes. Here's an example:
#!/bin/bash
colour1="red"
colour2="light blue"
colour3="dark green"
for X in "$colour1" $colour2" $colour3"
do
 echo $X
done
Can you guess what would happen if we left out the quotes in the for statement ? This indicates that variable names should be protected with quotes unless you are pretty sure that they do not contain any spaces.
'While' Loops
While loops iterate "while" a given condition is true. An example of this:
#!/bin/bash
X=0
while [ $X -le 20 ]
do
 echo $X
 X=$((X+1))
done
This raises a natural question: why doesn't bash allow the C like for loops
for (X=1,X<10; X++)
As it happens, this is discouraged for a reason: bash is an interpreted language, and a rather slow one for that matter. For this reason, heavy iteration is discouraged.

9) Functions:

When program gets complex we need to use divide and conquer technique. It means whenever programs gets complicated, we divide it into small chunks/entities which is know as function.
Function is series of instruction/commands. Function performs particular activity in shell i.e. it had specific work to do or simply say task. To define function use following syntax:
Syntax:
           function-name ( )
           {
                command1
                command2
                .....
                ...
                commandN
                return
           }
Where function-name is name of you function, that executes series of commands. A return statement will terminate the function. Example:
Type SayHello() at $ prompt as follows
$ SayHello()
{ echo "Hello $LOGNAME, Have nice computing"
return}
To execute this SayHello() function just type it name as follows:
$ SayHello
Hello surya, Have nice computing.
This way you can call function.

10)  Command Substitution:

Command Substitution is a very handy feature of the bash shell. It enables you to take the output of a command and treat it as though it was written on the command line. For example, if you want to set the variable X to the output of a command, the way you do this is via command substitution.

There are two means of command substitution: brace expansion and backtick expansion.
Brace expansion workls as follows:
$(commands) expands to the output of commands

This permits nesting, so commands can include brace expansions

Backtick expansion expands
`commands` to the output of commands
An example is given;:
#!/bin/bash
files="$(ls)"
web_files=`ls public_html`
echo "$files"      # we need the quotes to preserve embedded newlines in $files
echo "$web_files"  # we need the quotes to preserve newlines 
X=`expr 3 \* 2 + 4` # expr evaluate arithmatic expressions. man expr for details.
echo "$X"
The advantage of the $() substitution method is almost self evident: it is very easy to nest. It is supported by most of the bourne shell varients (the POSIX shell or better is OK). However, the backtick substitution is slightly more readable, and is supported by even the most basic shells (any #!/bin/sh version is just fine)

Note that if strings are not quote-protected in the above echo statement, new lines are replaced by spaces in the output.

11)  Shell Arithmetic:

Use to perform arithmetic operations.
Syntax:
expr op1 math-operator op2
Examples:
$ expr 1 + 3
$ expr 2 - 1
$ expr 10 / 2
$ expr 20 % 3
$ expr 10 \* 3
$ echo `expr 6 + 3`

12)  How to de-bug the shell script?

While programming shell sometimes you need to find the errors (bugs) in shell script and correct the errors (remove errors - debug). For this purpose you can use -v and -x option with sh or bash command to debug the shell script.
General syntax is as follows:
sh   option   { shell-script-name }
OR
bash   option   { shell-script-name }

Option can be

-v Print shell input lines as they are read.
-x After expanding each simple-command, bash displays the expanded value of PS4 system variable, followed by the command and its expanded arguments.

5 comments:

  1. Good tutorial thanks...

    ReplyDelete
  2. Nice Briefing dude, thank you

    ReplyDelete
  3. scripting simplified :)

    ReplyDelete
  4. Hi All,

    Can anyone send me script which will stop all the services and will reboot the tomcat servers. Please send it to om.omprakash.om@gmail.com

    Thank You.

    ReplyDelete