Skip to content

Download SLIDE-C02-bash-EN.pdf
Download C02-bash-EN.pdf

The variables

Variables ?

A variable has 2 elements :

  • the name
  • the value --> $name

Specific variables : environment

An environment variable is a dynamic variable used by processes or applications to define information paths or shortcuts. You can visualize all your environment variables with the env SHELL command. Usually all the environment variable are in capital case.

  • PATH
  • PS1
  • TERM
  • HOME
  • SHELL

PATH

PATH is a list of directory. With bash (and not sh) you don't have to write the absolute or relative path of a command. If the command you type exist in one of this directory, bash will call it.

isen@localhost:~$ echo $PATH
/sbin/:/home/isen/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
isen@localhost:~$ id
uid=1000(isen) gid=1000(isen) groupes=1000(isen)
isen@localhost:~$ which id
/usr/bin/id

PS1

PS1 stands for "Prompt String One" or "Prompt Statement One"

It is the first prompt string (that you see at a command line).

You can change it easily "live" or in your .bashrc file to be effective in every SHELL terminal

isen@localhost:~$ echo $PS1
echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$
isen@localhost:~$ PS1="Go for it->"
Go for it->echo $PS1
Go for it->

TERM

TERM variable defines the terminal type.

isen@localhost:~$ echo $TERM
xterm-256color

HOME

HOME is a Linux bash shell variable. It indicates the home directory of the current user. It also represent the default argument for the cd command. The value of this variable is also used when performing tilde expansion.

The value is set with the /etc/passwd file when the operating system is starting

isen@localhost:~$ echo $HOME
/home/isen
isen@localhost:~$ grep isen /etc/passwd
isen:x:1000:1000:A random user:/home/isen:/bin/bash

SHELL

The SHELL is an environment variable. The full pathname to the shell is in this environment variable.

The value is set with the /etc/passwd file when the operating system is starting

isen@localhost:~$ echo $SHELL
/bin/bash
isen@localhost:~$ grep isen /etc/passwd
isen:x:1000:1000:A random user:/home/isen:/bin/bash

List of SHELL linux

There is a lot of other shell on linux :

  • Shell Bourne (l'antique shell de Steve Bourne) : /bin/sh
  • Korn SHell, the David Korn's shell for UNIX : /bin/ksh and /bin/pdksh (freeware)
  • C SHell : /bin/csh
  • Zorn SHell : /bin/zsh
  • Bash (Bourne Again SHell, the Linux shell) : /bin/bash

Protect a variable

IFS

The IFS is an acronym for Internal Field Separator or Input Field Separator. The IFS is a special shell variable in Bash, ksh, sh, and POSIX. Let us see what IFS is and why you need to use it while writing shell scripts under Linux and Unix.

By default the IFS is compased by:

  • Carriage return
  • Tabulation
  • Space

Change IFS

IFS can be change before using a command or a function.

You may display the actual value of IFS with the following command

isen@localhost:$ echo "--$IFS--"
--
--

Warning: many Linux processes use the IFS.

Protect a variable : Syntax

Theres is three essential quotes in SHELL :

  • simple quote ': the string between these will not be interpreted
  • double quote ": the string between these will be interpreted (special character like $)
  • backquote `: the string between these will be a SHELL COMMAND, you can use $(COMMAND) to make it more readable

Variable visibility 1/4

All your variables will have a "scope", or a visibility. By default, the variables defined in a SHELL terminal are visible in your SHELL terminal and only in it.

isen@localhost:~$ Var=CONTENU
isen@localhost:~$ echo $Var
CONTENU
isen@localhost:~$ bash
isen@localhost:~$ ps
  PID TTY          TIME CMD
 12996 pts/2    00:00:00 bash
 13009 pts/2    00:00:00 bash
 13021 pts/2    00:00:00 ps
isen@localhost:~$ echo $Var

isen@localhost:~$ exit

Variable visibility 2/4

You will have to export a variable to make it visible for other CHILD SHELL Terminal or script

isen@localhost:~$ Var=CONTENU
isen@localhost:~$ echo $Var
CONTENU
isen@localhost:~$ export Var
isen@localhost:~$ bash
isen@localhost:~$ ps
   PID TTY          TIME CMD
  12996 pts/2    00:00:00 bash
  13406 pts/2    00:00:00 bash
  13435 pts/2    00:00:00 ps
isen@localhost:~$ echo $Var
CONTENU

Variable visibility 3/4

The same apply for your script, the scope of your variable will only be inside your script You may source another script to extend the vivibility of your variables to the other script

Consider two scripts Prog1.sh and Prog2.sh as bellow

isen@localhost:~$ cat Prog1.sh
#!/bin/bash
Var=CONTENU
echo "Prog1 : $Var"
./Prog2.sh
isen@localhost:~$ cat Prog2.sh
#!/bin/bash
echo "Prog2 : $Var"
isen@localhost:~$ ./Prog1.sh
Prog1 : CONTENU
Prog2 : 

Variable visibility 4/4

Now ! Consider two scripts Prog1.sh and Prog2.sh as bellow

isen@localhost:~$ cat Prog1.sh
#!/bin/bash
Var=CONTENU
echo "Prog1 : $Var"
source ./Prog2.sh
isen@localhost:~$ cat Prog2.sh
#!/bin/bash
echo "Prog2 : $Var"
isen@localhost:~$ ./Prog1.sh
Prog1 : CONTENU
Prog2 : CONTENU 

Protect a variable : Exemples

isen@localhost:~$ Var="ONE"
isen@localhost:~$ echo "$Var"_FILE
ONE_FILE
isen@localhost:~$ Var="ONE"
isen@localhost:~$ echo '$Var'_FILE
'$Var'_FILE
isen@localhost:~$ echo '${Var}'_FILE
${Var}_FILE
isen@localhost:~$ echo $Var_FILE
(nohing because Var_FILE dont exist)
isen@localhost:~$ echo ${Var}_FILE
ONE_FILE
isen@localhost:~$ls
C02 C03 C04 data EXAM Old ORIG
isen@localhost:~$ Var=$(ls) #or Var=`ls`
isen@localhost:~$ echo $Var
C02 C03 C04 data EXAM Old ORIG

Scripting base

What is a script

Instead of launching the commands directly in a terminal, we can write a text file with the shebang and the execution rights

username@hostname:~$ cat myfirstscript.sh
#!/bin/bash

echo toto
username@hostname:~$ chmod +x myfirstscript.sh
username@hostname:~$ ./myfirstscript.sh
toto

Advantages/Disadvantages

  • Advantages
    • More readable
    • Saved
    • Exportable
    • Debugging
  • Disadvantages
    • Debugging

Variable of a script

Name Description
\$0 the name of the current shell program.
\$1…\${n} the n parameters passed to the program (to the shell) when it is called.
\$# the number of parameters passed to the shell program call (not included the \$0 parameter)
\$* the list of parameters passed to the shell program call (not included the \$0 parameter)
\$\$ the current process number (there is a unique number per process on the machine)
\$\? the error code of the last command executed.

Example of use

username@hostname:~$ cat mysecondscript.sh
#!/bin/bash
echo "Thx to launch ${0}"
echo "There are ${#} arguments"
echo "They are : ${*} but the second is $2"
false
echo ${?}

username@hostname:~$ ./mysecondscript.sh toto titi tutu
Thx to launch ./mysecondscript.sh
There are 3 arguments
They are : toto titi tutu but the second is titi
1

Survival_Kit

Golden rules

  • Indent your script
  • Comment your script
  • Use a Naming rule
  • Declare your variable at the start of your script
  • Always test your entries
  • Give your script some "fresh air"
  • Test the return value of your SHELL commands ($?)
  • Use the man, level 1 (try a man -k)
  • Render your script executable : chmod +x Mynewscript.sh

Golden rules example 1/2

#BAD
if [[ -f $titi ]];then echo "your parameter is a file";cp $1 "$1".old;fi
#GOOD
if [[ -f ${Nom_Fichier_Saisi} ]]
then
    echo "your parameter is a file"
    cp $1 "${Nom_Fichier_Saisi}".old
fi

Golden rules example 2/2

if your script is waiting for an argument representing a name of a file.

#Test of arguments
if [ $# -lt 1 ]
then
    echo "You must give an argument for the script"
    exit 1
fi
#Test of the type of the first argument
if [ -e $1 ]
then
    echo "You must give an valid file name for the first argument for the script"
    exit 2
fi

Algo

IF Condition

IF condition

SO

------> Launch_action

END IF

Example of if condition

isen@localhost:~$ cat exampleIf.sh
#!/bin/bash
if [ $1 -eq 1 ]; then
        echo "The first argument is 1"
fi
isen@localhost:~$ bash exampleIf.sh 2

isen@localhost:~$ bash exampleIf.sh 1
The first argument is 1

if/else condition

IF condition

SO

------> Launch_action

ELSE

------> Launch_action

END IF

Example of if/else condition

isen@localhost:~$ cat exampleIfElse.sh
 #!/bin/bash
if [ $1 -eq 1 ]; then
        echo "The first argument is 1"
else
        echo "The first argument is not 1"
fi
isen@localhost:~$ exempleIfElse.sh 2
The first argument is not 1
isen@localhost:~$ exempleIfElse.sh 1
The first argument is 1

if/elif condition

IF condition

SO

------> Launch_action

ELSE IF other_condition

SO

------> Launch_action

END IF

Example of if/elif condition

isen@localhost:~$ exampleIfelIf.sh
 #!/bin/bash
if [ $1 -eq 1 ]; then
        echo "The first argument is 1"
elif [ $1 -eq 2 ]; then
        echo "The first argument is 2"
fi
isen@localhost:~$ exampleIfelIf.sh 10
isen@localhost:~$ exampleIfelIf.sh 1
The first argument is 1
isen@localhost:~$ exampleIfelIf.sh 2
The first argument is 2

if/elif/else condition

IF condition

SO

------> Launch_action

ELSE IF other_condition

SO

------> Launch_action

ELSE

------> Launch_action

END IF

Exemple of condition if/elif/else

isen@localhost:~$ cat exampleIfelIfElse.sh
 #!/bin/bash
if [ $1 -eq 1 ]; then
        echo "The first argument is 1"
elif [ $1 -eq 2 ]; then
        echo "The first argument is 2"
else
        echo "I do not understant"
fi
isen@localhost:~$ bash exampleIfelIfElse.sh 10
I do not understant
isen@localhost:~$ bash exampleIfelIfElse.sh 1
The first argument is 1
isen@localhost:~$ bash xampleIfelIfElse.sh 2
The first argument is 2

Tests - File

Operand Description example
-e filename true if filename exist [ -e /etc/shadow ]
-d filename true if filename is a directory [ -d /tmp/trash ]
-f filename true if filename is an ordinary file [ -f /tmp/Log.txt ]
-L filename true if filename is a symbolic link [ -L /home ]
-r filename true if filename is readable (r) [ -r /boot/vmlinuz ]
-w filename true if filename is modifiable (w) [ -w /var/log ]
-x filename true if filename is an executable (x) [ -x /sbin/halt ]

Tests - Strings

Operand Description example
-z txt true if the string is empty [ -z "${VAR}"]
-n txt true if the string is NOT empty [ -n "${VAR}"]
txt = txt true if the two string are equal [ "${VAR}" = "toto" ]
txt != txt true if the two string are NOT equal [ "${VAR}" != "toto" ]

Tests - Numeric

Operand Description example
num1 -eq num2 equality [ $Number -eq 42 ]
num1 -ne num2 not equal [ $Number -ne 42 ]
num1 -lt num2 lesser than (<) [ $Number -lt 42 ]
num1 -le num2 lesser or equal (<=) [ $Number -le 42 ]
num1 -gt num2 greater than (>) [ $Number -gt 42 ]
num1 -ge num2 greater or equal (>=) [ $Number -ge 42 ]

Example of test (1/2)

#!/bin/bash
# directory exists ? 1/2
test -d /home/isen
rc=$?
if [ $rc -ne 0 ]; then
    echo "The directory /home/isen does not exist"
fi

Example de test (2/2)

#!/bin/bash
# directory exists ? 2/2
if [ -d "/home/isen" ]; then
        echo "the directory /home/isen exists"
fi
# comparison of 2 strings
if [ "toto" = "titi" ]; then
        echo "toto is not equal to titi"
fi

While loop

WHILE condition

DO

------> Launch_action

RESTART

Example of while loop (1/2)

isen@localhost:~$ cat while.sh
#!/bin/bash
a=0
while [ $a -le 3 ]
do
    echo "$a"
    a=$(( $a + 1 ))
done

isen@localhost:~$ bash while.sh
0
1
2
3

Example of while loop (2/2)

while true; do
    echo $RANDOM
done

The bash is compiled as a 64-bit monothread. With this command your bash will use 100% of a CPU core. To protect your CPU, always put an "useless/time-out" action

while true; do
    echo $RANDOM
    sleep 1
done

for loop

FOR variable IN value1 value2 value3

DO

------> Launch_action

NEXT_ACTION

Example of for loop (1/2)

isen@localhost:~$ cat for1.sh
#!/bin/bash
for var in 'value1' 'value2' 'value3'; do
    echo "Var =  ${var}" ;
done

isen@localhost:~$ bash for1.sh
Var = value1
Var = value2
Var = value3

Example of for loop (2/2)

To get closer to the c code (this syntax is not widely used in bash):


isen@localhost:~$ cat for2.sh
#!/bin/bash
for i in $(seq 0 2)
do
    echo $i
done

isen@localhost:~$ bash for2.sh
0
1
2

This syntax $(seq 0 3) is equivalent to ((i=0;i<=3;i++))

Case/Esac

case ${vars} in
    1)  command1
        command1bis
        ;;
    2)  command2
        command2bis
        ;;
    *)  commanddefault
        commanddefault2
        ;;
esac

Example of Case/Esac

isen@localhost:~$ cat myScriptCase.sh
#!/bin/bash
case ${1} in
    toto) echo "toto is a beautifull name";;
    titi) echo "I prefer toto as a name";;
    *) echo "i do not understand"
esac

isen@localhost:~$ bash myScriptCase.sh toto
toto is a beautifull name
isen@localhost:~$ bash myScriptCase.sh titi
I prefer toto as a name
isen@localhost:~$ bash myScriptCase.sh Loic
i do not understand

BREAK/CONTINUE

isen@localhost:~$ cat for3.sh
#!/bin/bash
for var in value1 value2 value3 value4 value5; do
    [ "$var" = "value2" ] && continue
    [ "$var" = "value4" ] && break
    echo $var
done

isen@localhost:~$ bash for3.sh
value1
value3

BREAK = stop the loop

CONTINUE = go to the next iterration

Process management

Linux being a multitasking system, several programs can run at the same time.

When a program is started, a process is created. This is an active entity that has characteristics (priority, registers, ordinal counter, memory, etc.). Some characteristics may change over time

The system identifies the processes using an identifier (PID = Process IDentification).

The management of processes in Linux is said to be hierarchical.

A process can itself create another process (fork + exec). The created process is called a child process. The creator is called the parent process.

nice & renice

The nice and renice commands allow you to set or change the priority of a process. The range of possible values is -20 (most favorable priority) to 19 (least favorable).

isen@localhost:~$ nice -n -20 find / -type f -name "*.sh"
isen@localhost:~$ renice 20 7643

kill

The kill command sends a signal to a process. Overlays to the kill command exist killall, pgrep / pkill, xkill

isen@localhost:~$ kill 456
isen@localhost:~$ kill -9 -1
isen@localhost:~$ pkill firefox

Managing tasks in an interactive session

Interactive processes are started and managed from the user's terminal. There are 2 modes:

  • Foreground mode

  • Background mode

Managing tasks in an interactive session - Foreground mode

The process monopolizes the terminal until its termination

isen@localhost:~$ sleep 10
[...]

Managing tasks in an interactive session - Mode background

The process works in parallel with the terminal

isen@localhost:~$ sleep 10 &
[1] 3384
$

The "ctrl-z" key sequence and the commands "jobs, bg, fg commands" allow you to switch a process from one mode to the other.


Synthesis


Display the processes

You can use the SHELL command ps to display all the processes currently in execution on your computer

example to see the processes belonging to your current SHELL :

isen@localhost:~$ ps
   3837 pts/2    00:00:00 bash
 137967 pts/2    00:00:09 evince
 144605 pts/2    00:00:00 ps

example to see the processes belonging to you current owner :

isen@localhost:~$ ps -u isen
   PID TTY          TIME CMD
   2053 ?        00:00:02 systemd
   2054 ?        00:00:00 (sd-pam)
   2059 ?        00:04:16 pulseaudio
....