Concevez des scripts qui exĂ©cutent des commandes de type "terminal" đŸ–„

Le shell scripting avec Bash

Un Shell est une interface utilisateur du systĂšme d’exploitation. Il est la plus haute des interfaces des systĂšmes Unix, par opposition Ă  la couche de bas-niveau, appelĂ©e Noyau.
Il existe plusieurs Shells qui sont tous basés sur SH. Bash est celui utilisé par la plupart des systÚmes GNU/Linux.
Le Shell Scripting permet d’automatiser des commandes du terminal, Ă  l’aide d’une programmation qui reste limitĂ©e.

Executable Shebang


#!/bin/bash

# Executable shebang
# La premiere ligne n'est pas un commentaire ;)
# Elle specifie que le fichier s'execute avec bash
# (donc l'extention de fichier n'est plus obligatoire)

echo "test"

Ajouter le droit d’execution

chmod +x script_shebang

À la place du shebang on peut utiliser la commande …

bash /chemin/vers/le/script.sh

Les variables


# Il n'y a pas de typage, tout est chaine de caracteres

# Exemple de commande -> /bin/echo -e "Hello"
# $0 => /bin/echo
# $1 => "-e"
# $2 => "Hello"
# $* => "-e 'Hello'"
# $# => 2

var="variable var"
echo $var # $ Permet d'afficher la valeur de la variable

unset var # detruit la variable
echo $var

var=$1 # Affiche le premier argument de la commande
echo $var

var=$* # Affiche tous les arguments
echo $var
echo ${var}
echo "$var"
echo '$var' # Les simples quotes affichent le nom de la variable dans ce cas

echo ${var:2} # Recupere la chaine en supprimant les 2 premiers carateres

echo ${var:2:4} # Recupere 4 caractere a partir du 3eme inclus

echo ${#var} # Longeur de la variable

État de sortie


# Etats de sortie:
# 0 -> OK
# Autre -> Code erreur pour le programme

echo "salut"
echo $? # Obtenir l'etat de sortie de la commande precedente ( => 0)

dfghjklpoiuyfvki
echo $? # retourne le code erreur (commande introuvable)  ( => 127)

exit 123

# Si on fait echo $? apres la fermeture du script, on aura 123
echo "cette commande ne sera pas executee"

Conditions (Bash tests)


############# Chaines #############
# c1 = c2, vrai si c1 et c2 sont egaux
# c1 != c2, vrai si c1 et c2 sont différents
# -z c, vrai si c est la chaine vide
# -n c, vrai si c n'est pas la chaine vide

############# Pour les nombres #############
# n1 -eq n2, vrai si n1 et n2 sont egaux (equal)
# n1 -ne n2, vrai si n1 et n2 sont differents (non equal)
# n1 -lt n2, vrai si n1 est strictement inferieur a n2 (lower than)
# n1 -le n2, vrai si n1 est inferieur ou egal a n2 (lower or equal)
# n1 -gt n2, vrai si n1 est strictement superieur  n2 (greater than)
# n1 -ge n2, vrai si n1 est superieur ou egal  n2 (greater or equal)

############# Pour les expressions #############
# ! e, vrai si e est faux
# e1 -a e2, vrai si e1 et e2 sont vrais
# e1 -o e2, vrai si e1 ou e2 est vrai

test 4 -gt 3
echo $? # => 0 DONC VRAI !!! (pas comme d'hab car "etat de sortie bash"..)
test 4 -lt 3
echo $? # => 1 DONC FAUX !!!

# Une autre ecriture, attention aux espaces vers les crochets
[ 4 -gt 3 ] && echo $?

############# if #############
var=3
if [ $var -lt 3 ]; then
	echo '$var -lt 3'
elif [ $var -le 3 ]; then
	echo '$var -le 3'
else
	echo 'else'
fi
if [ $var = 3 ]; then echo "'=' sert aussi a comparer"; fi

############# case #############
case $var in
	1|2)
		echo '$var vaut 2 ou 3'
	;;
	3|4)
		echo '$var vaut 3 ou 4'
	;;
	5)
		echo '$var vaut 5'
	;;
	*)
		echo '$var vaut... autre chose...'
	;;
esac

############# COMPOSITION #############
# cmd1 ; cmd2	Sequentielle
# cmd1 & cmd2	Parallele
# cmd1 || cmd2	Sur erreur
# cmd1 && cmd2	Sur succes

[ $var ] && echo 123  || echo "probleme chef'"
[ $varnull ] && echo 123 || echo "probleme chef'"

Opérations


############# Operateurs #############
# +	Addition
# -	Soustraction
# *	Multiplication
# **	Puissance (Bash > 2.02)
# /	Division
# %	Modulo
# Bash ne supporte pas les nombres a virgule !!! 2/5 
# Pour des calcules plus complexes voir le langage bc (man bc)

############# Affectation arithmetique #############
# +=
# -=
# *=
# /=
# %= (Affectation du reste de la division)

############# Operateurs binaires #############
# << decalage d'un bit a gauche (multiplication par 2) # >> decalage d'un bit a droite (division par 2)
# & ET binaire
# | OU Inclusif binaire
# ~ NON binaire
# ^ XOR (ou exclusif) binaire
# Ils peuvent etre associes a l'affectation <<= # Le symbole ! permet d'inverser le retour ############# Changement de base ############# # Nombre precede de 0 -> base 8 (Attention! 06443->base8)
# Nombre precede de 0x -> base 16 
# Autres bases : BASE# Ex: 64#...

############# Calculs #############
# let 'var = 3+2'
# ou doubles parentheses -> bc plus de fonctionnalites
# (( var = 3+2 )) ou (( var++ )) ou echo $(( var = 3**2 ))

let 'var=5+2'; echo $var # -> 7

(( resultat = 5/2 ))
echo $resultat

(( entier = 5/2 )) ; (( reste = 5%2 ))
echo "entier -> $resultat"
echo "reste -> $reste"

(( entier = 5/2, reste = 5%2 ))
echo "entier -> $resultat - reste -> $reste" # -> entier 2 - reste 1

Boucles


############# FOR #############
# for var in list
# do
# 	echo $var
# done
#
# for (( i=1 ; i<=5 ; i++ )) # /!\ ce n'est pas une evaluation arithmetique # do # echo $i # done ############# WHILE ############# # while cmd # do # echo "coucou" # done ############# UNTIL ############# # until cmd # do # echo "coucou" # done ############# Controle de boucle ############# # break -> sortir de la boucle.
# break 2 -> sortir de 2 niveau de boucles
# continue -> tour de boucle suivant
	
############# Exemple #############
user_entry=""
while [ "$user_entry" != "coucou" ]
do
	read -p "Vas-y ecris 'coucou' ;) : " user_entry
done
echo "T'es trop fort !"

user_entry2=""
until [ "$user_entry2" = "coucou" ]
do
	read -p "Vas-y ecris 'coucou' ;) : " user_entry2
done
echo "T'es trop fort !"

for couleur in bleu blanc rouge
do
	echo $couleur
done

for (( i=0 ; i<10 ; i++ ))
do
	echo $i
	if [ $i -ge 3 ]; then
		break
	fi
done

Substitution de commande


# Syntaxe : `ma commande`	ou 	$(ma commande)
# Attention c'est ` et PAS CA " ou CA ' ou CA ‘ ou CA ’
# [ -x `wich bash` ]
# for i in `seq 1 100` ; do
# variable=`<fichier`	ou 	variable=`cat fichier`
# (moins performant avec cat car nouveau process)
	

Documents intégrés


# Utile pour manipuler une application
vim fichier <<EOT
i
blah blah blah
^[
:wq !
EOT
	
# Pour ne pas interpreter les tabulations:
# cat <<-EOT ......
	

Sous-shells et shells restreints


# On a 3 shells qui sont complettement independants
# 1 shell 'racine' et 2 'sous-shells'
pwd
( cd / ; pwd ) & ( cd /etc ; pwd )
pwd

# Le mode restreint permet de gagner en securite
# Au sens large. CAD qu'il empeche :
# - Sortir du repertoire de travail (cd)
# - Changement de valeur des variables d'environnement ($PATH, $SHELL, $BASH_ENV, $ENV)
# - Lecture et remplacement d'options d'options d'environnement des shell $SHELLOPTS
# - Redirection de sortie
# - Appel de commandes contenants un ou plusieurs /
# - Substituer un processus different de celui du shell (exec)
# - Sortir du mode restreint au sain du script

set -r
cd .. # -> Erreur

Fonctions


function ma_fonction_1
{
	echo "Syntaxe 1"
	echo $1 $2
	return 123
}
ma_fonction_2 ()
{
	echo "Syntaxe 2"	
	echo $1 $2
	# return "retour f2"
	# -> erreur seulement des nombres en return
}
ma_fonction_1 "arg 1" "arg 2" || echo $? # 123
echo "----"
ma_fonction_2 "arg 1" "arg 2"

Alias


# Les alias sont utilises sont des raccourcis
# Utilises dans .bashrc par exemple
alias JuJu="ls"
JuJu 		# effectue un ls
unalias JuJu 	# Penser a suppr l'alias

Source (include)


# Inclure un fichier dans un autre
# Comme si on faisait un copier/coller
source mon_fichier	# Syntaxe 1
. mon_fichier_2		# Syntaxe 2

Listes et tableaux


# Les tableau de bash sont plutot
# des listes, car pas de taille fixe

tab=("val1" "val2" "val3")
echo ${tab[0]} # -> val1
echo ${tab[1]} # -> val2
echo ${tab[2]} # -> val3

tab[0]="nouvelle valeur"
echo ${tab[0]} # -> nouvelle valeur

echo ${#tab[@]} # -> 3 (longeur du tab)
echo ${#tab[*]} # -> 3 (IDEM)
echo ${!tab[@]} # -> 0 1 2
echo ${tab[@]}  # -> nouvelle valeur val2 val3

echo ${tab[0]} # -> nouvelle valeur
echo ${tab[1]} # -> val2
echo ${tab[2]} # -> val3

echo "--------"

for i in ${!tab[@]}
do
    echo "$i : ${tab[$i]}"
done
	

DĂ©bogage


# Pas d'outil specialise
# Astuces :

# - echo a tous les points cles
# - Utiliser la fonction de Stefano Falsetto (debecho) et activer mode debug
# - Filtrer les sorties grace a tree
# - Utiliser la variable LINENO qui prendra la valeur de la ligne du script
# - Tester si la variable est un nombre
# - Intercepter le signal EXIT avec trap pour afficher un message ĂȘrsonnaliser en cas d'arret du script

Options de bash


#!/bin/bash -x

# Pour modifier le comportement du script
# -n, -v, -x, ...

# Au niveau du shebang : #!/bin/bash -x
echo coucou
echo coucou

# Ou en cours d'execution : set -X ou set +X pour retablir
set +x
echo coucou
echo coucou

set -v
echo coucou
echo coucou

# Voir les nombreuses autres possibilites sur le net...