Advanced Shell Scripting

3 minute read

This article has been migrated from my original post at embeddedinn.wordpress.com.

Shell scripting refers to an automated way of interacting with a computer system over command line interface (CLI) . This article deals specifically with scripting with the bash shell

Shebang

Shebang is the method used in bash scripting to declare the interpreter to be used for the rest of the script. It is represented as #!. eg:

#!/bin/sh

Execution

When interacting with external programs or scripts (referred to as, file in general) shell scripts uses three major execution modes

source

In this mode, the external file is executed in the current shell environment. Exit status of the last executed command is passed on as the return value. eg:

source ./child.sh

or simply

. ./child.sh

eval

All arguments to eval are concatenated into one string and executed as a new command. eg:

eval "hello $USER"

exec

The command specified as the argument to exec will replace the shell . The arguments becomes arguments to the command.

Parallel Processing

Spawning parallel processes

A task can be run in the background by appending an & to the end of the command. eg:

./child1 &
./child2 &

A waiting parent

Once child a process is spawned, the parent has to wait until the child process returns. To wait for all children, put a wait at the end of the script. eg:

./child1 &
./child2 &
wait
echo " exiting since all children are done"

To wait for a specific child, the child PID has to be passed to the wait command. The child PID can be fetched from the $! variable as soon as the child is spawned. eg:

./child1 &
PID1=$!
./child2 &
PID2=$!
wait PID1 PID2

To fetch the return values of the children, use the $? variable immediately after the wait for the corresponding child. eg:

./child1 &
PID1=$!
./child2 &
PID2=$!
wait PID1 
RET1=$?
wait PID2
RET2=$?

Irrespective of when the child finished processing, the return value will be collected when wait is called on its PID

Pitfalls

If the parent is killed while waiting for the children to exit (say, by a SIGINT (ctrl+c)), the children becomes Zombies and will start to eat-up system resources. To avoid this, install a trap to catch the probable kill signals.eg:

trap “kill -9 $child; echo child killed;”  SIGHUP SIGINT SIGTERM

Colorizing

To get color prints in the shell, use the following syntax

echo -e "33[COLORm Hello World"

or

printf "\e[COLORm Hello World"

List of colors available are

color foreground Background
Black 30 40
Red 31 41
Green 32 42
Yellow 33 43
Blue 34 44
Magentha 35 45
Cyan 36 46
White 37 47

For example, to print a text in red with yellow background, and then reset the colors back to white text in black background , one fo the following can be done:

echo -e "33[31;43m Deleting33[37;40m"
printf "\e[31;43m Deleting\e[37;40m"

Further possible effects are

ANSI Code Meaning
0 Normal
1 Bold
4 Underline
5 Blink
7 Reverse Video

For example, to print bold red text in yellow background and then reset the colors back to white text in black background , one of the following can be done.

echo -e "33[1;31;43m Deleting33[0;37;40m"
printf "\e[1;31;43m Deleting\e[0;37;40m"

Outliving the sessions

When a session terminates, all processes that started from the session will receive a SIGHUP and will thus be terminated . However, the session can be outlived in one of the two ways.

  • Install a SIGHUP trap at the beginning of the script
    trap "echo 'I wont go down'" SIGHUP

  • Run your process under nohup
    nohup is a POSIX command that will do the SIGHUP trapping for you.
    #nohup <scriptName.sh> &

  • disown the job (background process)
    If the process to outlive the session is already in the background, it can be “disowned” so that the session termination will not terminate the process. one fo the following can be done for this.

    #my_script.sh &  
    disown <PID of my_script.sh>
    

    #my_script.sh & disown

using shopt to make shell more intelligent

shopt provides a bunch of options to make the shell more “intelligent”

I use this in my .bashrc

shopt -s autocd direxpand dirspell histverify checkwinsize cdspell cdable_vars

I will keep adding more or these interesting shell scripting stuff here. So, keep tuned . . .

Leave a comment