Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Linux Shell Scripting Cookbook

You're reading from   Linux Shell Scripting Cookbook Do amazing things with the shell and automate tedious tasks

Arrow left icon
Product type Paperback
Published in May 2017
Publisher
ISBN-13 9781785881985
Length 552 pages
Edition 3rd Edition
Tools
Arrow right icon
Authors (3):
Arrow left icon
Clif Flynt Clif Flynt
Author Profile Icon Clif Flynt
Clif Flynt
Sarath Lakshman Sarath Lakshman
Author Profile Icon Sarath Lakshman
Sarath Lakshman
Shantanu Tushar Shantanu Tushar
Author Profile Icon Shantanu Tushar
Shantanu Tushar
Arrow right icon
View More author details
Toc

Table of Contents (14) Chapters Close

Preface 1. Shell Something Out FREE CHAPTER 2. Have a Good Command 3. File In, File Out 4. Texting and Driving 5. Tangled Web? Not At All! 6. Repository Management 7. The Backup Plan 8. The Old-Boy Network 9. Put On the Monitors Cap 10. Administration Calls 11. Tracing the Clues 12. Tuning a Linux System 13. Containers, Virtual Machines, and the Cloud

Functions and arguments

Functions and aliases appear similar at a casual glance, but behave slightly differently. The big difference is that function arguments can be used anywhere within the body of the function, while an alias simply appends arguments to the end of the command.

How to do it...

A function is defined with the function command, a function name, open/close parentheses, and a function body enclosed in curly brackets:

  1. A function is defined as follows:
        function fname() 
        { 
            statements; 
        }  

Alternatively, it can be defined as:

        fname() 
        { 
            statements; 
        } 

It can even be defined as follows (for simple functions):

        fname() { statement; }
  1. A function is invoked using its name:
        $ fname ; # executes function
  1. Arguments passed to functions are accessed positionally, $1 is the first argument, $2 is the second, and so on:
        fname arg1 arg2 ; # passing args

The following is the definition of the function fname. In the fname function, we have included various ways of accessing the function arguments.

        fname() 
        { 
           echo $1, $2; #Accessing arg1 and arg2 
           echo "$@"; # Printing all arguments as list at once 
           echo "$*"; # Similar to $@, but arguments taken as single  
           entity 
           return 0; # Return value 
         }

Arguments passed to scripts can be accessed as $0 (the name of the script):

    • $1 is the first argument
    • $2 is the second argument
    • $n is the nth argument
    • "$@" expands as "$1" "$2" "$3" and so on
    • "$*" expands as "$1c$2c$3", where c is the first character of IFS
    • "$@" is used more often than $*, since the former provides all arguments as a single string
  • Compare alias to function
  • Here's an alias to display a subset of files by piping ls output to grep. The argument is attached to the end of the command, so lsg txt is expanded to ls | grep txt:
        $> alias lsg='ls | grep' 
        $> lsg txt 
          file1.txt 
          file2.txt 
          file3.txt 
  • If we wanted to expand that to get the IP address for a device in /sbin/ifconfig, we might try the following:
        $> alias wontWork='/sbin/ifconfig | grep' 
        $> wontWork eth0 
        eth0  Link  encap:Ethernet  HWaddr 00:11::22::33::44:55 
  • The grep command found the eth0 string, not the IP address. If we use a function instead of an alias, we can pass the argument to the ifconfig, instead of appending it to the grep:
        $> function getIP() { /sbin/ifconfig $1 | grep 'inet ';  } 
        $> getIP eth0 
        inet addr:192.168.1.2 Bcast:192.168.255.255 Mask:255.255.0.0

There's more...

Let's explore more tips on Bash functions.

The recursive function

Functions in Bash also support recursion (the function can call itself). For example, F() { echo $1; F hello; sleep 1; }.

Fork bomb

A recursive function is a function that calls itself: recursive functions must have an exit condition, or they will spawn until the system exhausts a resource and crashes.

This function: :(){ :|:& };: spawns processes forever and ends up in a denial-of-service attack.

The & character is postfixed with the function call to bring the subprocess into the background. This dangerous code forks processes forever and is called a fork bomb.

You may find it difficult to interpret the preceding code. Refer to the Wikipedia page h t t p ://e n . w i k i p e d i a . o r g /w i k i /F o r k _ b o m b for more details and interpretation of the fork bomb.
Prevent this attack by restricting the maximum number of processes that can be spawned by defining the nproc value in /etc/security/limits.conf.

This line will limit all users to 100 processes:

 hard nproc 100

Exporting functions
Functions can be exported, just like environment variables, using the export command. Exporting extends the scope of the function to subprocesses:

export -f fname
$> function getIP() { /sbin/ifconfig $1 | grep 'inet '; }
$> echo "getIP eth0" >test.sh
$> sh test.sh
  sh: getIP: No such file or directory
$> export -f getIP
$> sh test.sh
  inet addr: 192.168.1.2 Bcast: 192.168.255.255 Mask:255.255.0.0

Reading the return value (status) of a command

The return value of a command is stored in the $? variable.

cmd;
echo $?;

The return value is called exit status. This value can be used to determine whether a command completed successfully or unsuccessfully. If the command exits successfully, the exit status will be zero, otherwise it will be a nonzero value.

The following script reports the success/failure status of a command:

#!/bin/bash 
#Filename: success_test.sh 
# Evaluate the arguments on the command line - ie success_test.sh 'ls | grep txt' 
eval $@ 
if [ $? -eq 0 ]; 
then 
    echo "$CMD executed successfully" 
else 
    echo "$CMD terminated unsuccessfully" 
fi

Passing arguments to commands

Most applications accept arguments in different formats. Suppose -p and -v are the options available, and -k N is another option that takes a number. Also, the command requires a filename as argument. This application can be executed in multiple ways:

  • $ command -p -v -k 1 file
  • $ command -pv -k 1 file
  • $ command -vpk 1 file
  • $ command file -pvk 1

Within a script, the command-line arguments can be accessed by their position in the command line. The first argument will be $1, the second $2, and so on.
This script will display the first three command line arguments:

echo $1 $2 $3

It's more common to iterate through the command arguments one at a time. The shift command shifts eachh argument one space to the left, to let a script access each argument as $1. The following code displays all the command-line values:

$ cat showArgs.sh
for i in `seq 1 $#`
do
echo $i is $1
shift
done
$ sh showArgs.sh a b c
1 is a
2 is b
3 is c
You have been reading a chapter from
Linux Shell Scripting Cookbook - Third Edition
Published in: May 2017
Publisher:
ISBN-13: 9781785881985
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image