Attention: Ce contenu est un complément des documents ‘Les scripts Linux (P1 et P2)’, disponibles sur LEA. Utilisé seul, il ne permet pas d’atteindre la compétence « Scripts Bash’ du cours 420-1C5.
Il est important de consulter les documents P1 et P2 pour être en mesure de réussir l’épreuve synthèse.
Note: Avant de commencer, afficher le ‘shell’ courant avec
$ echo $SHELL /bin/bash
Exemple 01 – Affichage
#!/bin/bash # La ligne précédente est nommée 'script shebang ou bang line' # Ce script efface le terminal et affiche des info à l'écran clear # Efface l'écran echo "Exemple 01" echo "----------------------------------------------------------" echo "Début du script..." echo "Bonjour, $USER!" # $ pour obtenir le contenu d'une variable echo # Affiche une ligne vide echo "Voici la liste des utilisateurs connectés:" echo w echo echo "Initialisation de deux variables:" COLOUR="rouge" VALUE="3.14159256" echo -n "La couleur est $COLOUR et " # -n = pas de retour de chariot echo "le nombre est $VALUE" echo echo "Voilà, retour à l'invite." echo "----------------------------------------------------------" echo
Exemple 01.2 – Insérer des caractères de contrôle dans une chaine.
# Utilisation de echo -e echo '------------------------------------------' echo "Bonjour \n$USER !" echo '------------------------------------------' echo -e "Nous sommes le \n" ; date echo '------------------------------------------' echo -e "Bonjour \t$USER dont le UID est \n$UID" echo '------------------------------------------' echo -e 'Bonjour \t$USER dont le UID est \n$UID' echo '------------------------------------------'
Exemple 02 – Déverminage d’un script
# Tout le script bash -x exemple01 # Une partie # Utilisation de set -+x dans le script set -x # déverminage à partir d'ici w set +x # fin du déverminage
Exemple 03 – Passer des paramètres au script
#Exemple03 #!/bin/bash # Description: Afficher un message à partir de valeurs reçues en entrée. # ---------------------------------------------------------------------- # Param 1 : prénom # Param 2 : nom # Usage: ./Exemple02 prenom nom # ---------------------------------------------------------------------- echo "Bonjour $1 $2, bienvenue au cours sur les scripts bash." echo 'Bonjour $1 $2, bienvenue au cours sur les scripts bash.'
Exemple 03.2 – Boucler sur les paramètres reçus
# Traiter tous les paramètres reçus avec 'for in do' compteur=1 for num in "$@" do echo "param $compteur = $num" ((compteur++)) done
Exemple 04 – Instruction ‘if’ – Vérifier si le script a reçu des paramètres
#Exemple04 #!/bin/bash # Description: Vérifier si le script a reçu des paramètres # ---------------------------------------------------------------------- # Param 1 : prénom # Param 2 : nom # Usage: ./Exemple04 # ---------------------------------------------------------------------- if [ $# -eq 0 ] # si nb param == 0 alors then echo "Usage: ./Exemple02 prenom nom" exit 1 # sortir du script avec un code d'erreur fi echo "Bonjour $1 $2, bienvenue au cours sur les scripts bash."
Il est aussi possible de vérifier si l’argument no 1 est vide:
if [ -z "$1" ] then echo "Désolé pour vous, mais il n'y a pas d'argument :-( !" fi
Exemple 05 – Saisie à partir du clavier
#!/bin/bash #Exemple05 - instruction read - Saisie à partir du clavier echo '--------------------------------------' echo "Entrez un prénom suivi du nom" read prenom nom echo echo "Bonjour $prenom $nom" echo '--------------------------------------' exit 0
Exemple 05.2 – Validation de la saisie avec [[ ||, &&]]
#!/bin/bash #Exemple05.2 - instruction read - Saisie à partir du clavier echo '--------------------------------------' echo "Entrez un prénom suivi du nom" read prenom nom # Note: le double [[]] permet l'utilisation de filtre et d'une syntaxe moderne. # Par exemple [[ $nom = "m"* ]] -> nom débute par 'm'. || pour OR et && pour AND if [[ "$prenom" == "" || "$nom" == "" ]] then echo "Erreur: Il faut enter un prénom suivi d'un nom!!" exit 1 fi echo echo "Bonjour $prenom $nom" echo '--------------------------------------' exit 0
Note: Les expressions complexes doivent être entre [[ … ]]. || = OR
Exemple 05.3 – Exemple 5.2 avec syntaxe ancienne []
#!/bin/bash #Exemple05c - instruction read - Saisie à partir du clavier echo '--------------------------------------' echo "Entrez un prénom suivi du nom" read prenom nom # Note: -0 = OR, -a = AND if [ -z "$prenom" -o -z "$nom" ] then echo "Erreur: Il faut enter un prénom suivi d'un nom!!" exit 1 fi echo echo "Bonjour $prenom $nom" echo '--------------------------------------' exit 0
Exemple 06 – Les variables d’environement
# Voici quelques variables d'environnement # Liste obtenue avec le commande 'set' BASH_VERSION HISTFILE HOME LOGNAME $ echo $BASH_VERSION # ----------------------------------------------- # Définir une variable d'ENV: # Note: Pas d'espace lors de la déclaration $ maVariable="Je suis moi" $ echo $maVariable # ------------------------------------------------- # Utilisation de caractères spéciaux dans la chaine $ message="Ce \"texte\" \\n contient des car spéciaux" $ msg3="Ligne 1\nLigne 2" $ echo -e "$msg3" # -------------------------------------------------------- # Définir une variable à partir du résultat d'une commande $ ladate=$(date +%Y-%m-%d) $ echo $ladate # Autre syntaxe possible (plus ancienne) - apostrophe inversé $ liste=`ls` $ echo $liste # ----------------------------------------------- # Rendre la variable disponible pour les scripts # La commande 'export' nomVariable $ export maVariable # ----------------------------------------------- # Supprimer une variable $ unset maVariable # ----------------------------------------------- # Substitution de variables tp="/version" echo $tp ver=$tp1 # la variable tp1 n’existe pas alors ver = une chaine vide, echo $ver # la variable 'ver' n'a pas été créée! ver=${tp}1 # Substitution de la variable tp echo $ver # /version1 # Note, il est aussi possible de l'écrire ainsi: ver="$tp"1
Exemple 07 – Les tableaux
# Déclarer un tableau $ amis[0]=Bob $ amis[1]=Bob $ amis[2]=Toto $ amis[3]=France $ echo ${amis[0]} # Afficher tous les éléments d'un tableau $ echo ${amis[@]}
# Utilisation de la commande 'if' # NOTE: [] est un synonyme de la commande 'test' # Voir: man test # -------------------------------------- # un si simple # if [ test ] # then # echo "le test est passé" # fi # on ferme toujours la condition par fi (if en verlan !) # et avec un else if et un else # if [ test ] # then # echo "le test est passé" # elif [ test2 ] # echo "le test2 est passé" # else # echo "les deux tests ont échoué" ##fi # -------------------------------------- num=10 # Definir une variable numérique echo "--------------------------------------" echo -e "Test sur un nombre:\n\n" if [ $num -lt 99 ] then echo "la variable est inférieure à 99" fi if [ $num -eq 11 ] then echo "la variable est égale à 11" fi echo "--------------------------------------" # Synthase compacte if [ "test" == "test" ]; then echo -ne "\nle test: " echo -n "if [ \"test\" == \"test\" ] " echo -e "est passé!\n" fi echo "--------------------------------------"
Exemple 09 – Tester si un fichier est présent dans le répertoire
#!/bin/bash #Exemple09 - Vérifier si un fichier est présent clear echo '--------------------------------------' echo -n "Entrez le nom d'un fichier: " read fichier if [ -a "$fichier" ] then echo -e "\nLe fichier $fichier est présent dans le dossier $(pwd)" else echo -e "\nErreur: Le fichier $fichier n'est pas présent dans le dossier $(pwd)" fi echo
Note: Voir le document de cours pour les détails sur l’utilisation de la commande ‘test’
Exemple 10 – Tester des valeurs numériques
#Exemple 10 #!/bin/bash # Comparer deux nombres avec l'instruction 'test' clear PI=31415 NBOR=16180 echo "Ce script bash compare deux nombres avec la commande 'test'" echo "-----------------------------------------------------------" echo # Note: Bash supporte seulement les nombres entiers. if test $PI -lt $NBOR # PI < NBOR ? then echo "$PI est plus petit que $NBOR" elif test $PI -gt $NBOR # PI > NBOR ? then echo "$PI est plus grand que $NBOR" else echo "$PI est égal à $NBOR" fi
Note: Il est possible de vérifier que la chaine saisie contient seulement des caractères numérique:
if [[ $nb == ?(-)+([0-9]) ]];then ; echo "$nb est un entier" ; fi
Référence: Bash Pattern matching
Exemple 10.2 – Tester si une chaine est vide
#Exemple 10.2 #!/bin/bash # Saisir deux nombres et les comparer avec l'instruction [ test ] clear echo -n "Entrez deux nombres entiers séparés par un espace: " read nb1 nb2 # Tester si deux valeurs ont été saisies: # Combinaison de tests avec && (AND) et || (OR) # test -z, tester si une chaine est vide if [ -z $nb1 ] || [ -z $nb2 ] ; then echo "Erreur: Il faut fournir deux nombres!!" exit 1 fi # Note: Bash supporte seulement les nombres entiers. if test $nb1 -lt $nb2 # nb1 < nb2 ? then echo "$nb1 est plus petit que $nb2" elif test $nb1 -gt $nb2 # nb1 > nb2 ? then echo "$nb1 est plus grand que $nb2" else echo "$nb1 est égal à $nb2" fi
Exemple 11 – Vérifier si un groupe existe dans le fichier /etc/group
#Exemple 11 #!/bin/bash # Saisir un nom de groupe puis vérifier s'il existe avec la commande 'grep' clear echo -n "Entrez le nom d'un groupe: " read groupe # Tester si le nom du groupe a été saisie: if test -z $groupe ; then echo "Erreur: Il faut fournir le nom d'un groupe!" exit 1 fi # Note: grep -q = ne pas afficher le résultat à l'écran if grep -q $groupe /etc/group then echo "Le groupe: $groupe est présent dans le fichier /etc/group" else echo "Le groupe: $groupe n'est pas présent dans le fichier /etc/group" fi #------------------------------------------------------ # Autre façon de tester: grep -E "^$groupe:" /etc/group
Exemple 12 – Valeur de retour d’une commande
#Exemple 12 echo "Ce script retourne le nombre de paramètres reçus" echo "Cette valeur sera disponible, à la sortie du script, dans la variable '\$?'" # $# = nb de param reçu. exit $#
$ echo $?
Note: La variable $? est l’équivalent de ERRORLEVEL sous CMD de Windows.
Exemple 13 – Valider un choix multiple
#Exemple13 #!/bin/bash clear echo "Exemple d'utilisation de la commande 'case'" echo -e "-------------------------------------------\n" echo "---> case - exemple 1" read -p "Effacer le disque rigide O/N? " jaipeur case $jaipeur in # Note: Uitlisation de la substitution de variable pour former les mots oui et non. o|O) echo "Vous avex répondu ${jaipeur}ui :--( !" ;; n|N) echo "Sage décision d'avoir répondu ${jaipeur}on" ;; *) echo "Réponse erronée!" ; exit esac echo "---> case - exemple 2" read -p "Veuillez entrer une chaîne de caractères: " param case $param in 0|1|2|3|4|5|6|7|8|9) echo "$param est un chiffre" ;; [0-9][0-9]) echo "$param est un nombre à deux chiffres" ;; [a-zA-Z]*) echo "$param est un mot" ;; *) echo "$param est non prévu" ;; esac
Note: L’exemple précédent valide seulement des nombres à un ou deux caractères de long. Voici une solution plus élégante:
Exemple 14 – Utilisation de ‘shell pattern matching‘.
# Exemple 14 # Projet: 420-1C5.bash-file # Auteur: Alain Boudreault # Date: 2020.12.06 # Description: Tester un nombre avec 'pattern matching' # ----------------------------------------------------- # Note: Pour permettre le 'pattern matching' # La ligne suivante est nécessaire sous bash shopt -s extglob # Boucle principale du programme while true; do clear echo -n "Entrez un nombre long: " read unNombre case $unNombre in ( +([0-9]) ) echo "$unNombre est un nombre valide" break 2 ;; # // sortir des 2 blocs de code *) echo "$unNombre est invalide!" echo "Appuyer sur retour pour recommencer ..."; read;; esac # Fin du case done # Fin du while # break 2 pointe ICI echo "--- Fin du programme ---"
Exemple 15 – Une boucle while tant que fichier n’est pas trouvé
#!/bin/bash #Exemple15 # Début du programme clear echo -n "Entrez un nom de fichier: " read fichier while [ ! -e "$fichier" ] # Boucler tant que le fichier est inexistant do echo "Fichier $fichier introuvable, appuyer sur retour pour recommencer..." read clear echo -n "Entrez un nom de fichier: " read fichier done echo echo "--------------------------------------------------------" echo "Le fichier $fichier est présent sur le volume." echo
Exemple 15b – Normalisation de l’exemple précédent – Utilisation d’une fonction
#!/bin/bash #Exemple15b # Les fonctions function lireNomFichier () { echo "Entrez un nom de fichier" read fichier } # Début du programme clear lireNomFichier while [ ! -e "$fichier" ] # Boucler tant que le fichier est inexistant do echo "Fichier $fichier introuvable, appuyer sur retour pour recommencer..." read clear lireNomFichier done echo echo "--------------------------------------------------------" echo "Le fichier $fichier est présent sur le volume." echo
Exemple 15c – Une boucle sans fin
while true; do # ctrl+c pour quitter echo "Je suis une boucle sans fin - ;-)" done
Exemple 15d – Afficher l’heure dans une boucle while
#Exemple15d #!/bin/bash # Afficher l'heure à toutes les secondes while true do clear echo -n "Bonjour $USER, il est: "; date +"%H.%m.%S" echo "CTRL+C pour quitter" sleep 1 done
Exemple 16 – Boucler sur un contenu de redirection
#Exemple16 #!/bin/bash fich="/etc/passwd" numeroLigne=1 while read ligne do if [[ $ligne = "m"* ]] # Afficher la ligne si le texte commence par 'm' then echo "----------------------------------------------------------------" echo "Résultat trouvé à la ligne $numeroLigne" echo $ligne echo "----------------------------------------------------------------" fi ((numeroLigne+=1)) done < "${fich}"
Exemple 17 – until do … done
#!/bin/bash #Exemple17 until echo -e "Entrez le nom du fichier à afficher" read fich [ -e "$fich" ] # NOTE: Boucle tant que cette condition est fausse do echo -e "Fichier inexistant, saisie à recommencer..." done echo "---------------------------------------------------------" echo "Voici le contenu du fichier: $fich" echo cat $fich
Exemple 18 – choix multiple via un menu, select in …
#Exemple18 #!/bin/bash # Exemple d'utilisation de l'instruction select PS3="Entrez le numéro de votre choix -> " echo "Que désirez-vous boire ?" select boisson in "Rien, merci" "Café" "Thé au lait" "Chocolat" do if [ -z "$boisson" ] then echo "Erreur : entrez un des chiffres proposés." elif [ "$REPLY" -eq 1 ] then echo "Au revoir !" break else echo "Vous avez fait le choix numéro $REPLY ..." echo "Le $boisson vous sera servi dans un instant !" echo "Autre chose ?" fi echo done
La commande ‘getent‘ permet de vérifier des paramètres systèmes.
Par exemple, pour vérifier si l’utilisateur ‘toto’ existe;
$ getent passwd toto
Si la commande retourne une valeur autre que ‘0’ c’est que l’opération n’a pas réussit.
$ echo $?
$ 2
Pour supprimer les messages, normaux et erreurs, d’une commande:
$ getent passwd toto &> /dev/null
$ addgroup 456abc &> /dev/null
Voir la documentation ‘man getent’
Action – Écrire un script ‘creerGroupes’;
Voici ce que produit le script:
Exemple 1 - avec des groupes existants $ sudo ./creerGroupes users root ---------------------------------------- Traitement du groupe 'users' Erreur: Le groupe 'users' existe déjà ---------------------------------------- Traitement du groupe 'root' Erreur: Le groupe 'root' existe déjà 0 groupe sur 2 de créé Exemple 2 - avec un nom invalide $ sudo ./creerGroupes 444abc ---------------------------------------- Traitement du groupe '444abc' Erreur: Nom du groupe invalide: '444abc' 0 groupe sur 1 de créé Exemple 3 - avec trois nouveaux groupes valides $ sudo ./creerGroupes groupe01 groupe02 groupe99 ---------------------------------------- Traitement du groupe 'groupe01' Création du groupe 'groupe01' réussit ---------------------------------------- Traitement du groupe 'groupe02' Création du groupe 'groupe02' réussit ---------------------------------------- Traitement du groupe 'groupe99' Création du groupe 'groupe99' réussit 3 groupes sur 3 de créés
Note: Il y aura une question semblable à l’épreuve synthèse.
Sortie et reprise d’une boucle – Voir le document pdf ‘Les scripts Linux (P2)’
Les fonctions – Voir le document pdf ‘Les scripts Linux (P2)’
Divers – Voir le document pdf ‘Les scripts Linux (P2)’
test: test [expr] Evaluate conditional expression. Exits with a status of 0 (true) or 1 (false) depending on the evaluation of EXPR. Expressions may be unary or binary. Unary expressions are often used to examine the status of a file. There are string operators and numeric comparison operators as well. The behavior of test depends on the number of arguments. Read the bash manual page for the complete specification. File operators: -a FILE True if file exists. -b FILE True if file is block special. -c FILE True if file is character special. -d FILE True if file is a directory. -e FILE True if file exists. -f FILE True if file exists and is a regular file. -g FILE True if file is set-group-id. -h FILE True if file is a symbolic link. -L FILE True if file is a symbolic link. -k FILE True if file has its `sticky' bit set. -p FILE True if file is a named pipe. -r FILE True if file is readable by you. -s FILE True if file exists and is not empty. -S FILE True if file is a socket. -t FD True if FD is opened on a terminal. -u FILE True if the file is set-user-id. -w FILE True if the file is writable by you. -x FILE True if the file is executable by you. -O FILE True if the file is effectively owned by you. -G FILE True if the file is effectively owned by your group. -N FILE True if the file has been modified since it was last read. FILE1 -nt FILE2 True if file1 is newer than file2 (according to modification date). FILE1 -ot FILE2 True if file1 is older than file2. FILE1 -ef FILE2 True if file1 is a hard link to file2. All file operators except -h and -L are acting on the target of a symbolic link, not on the symlink itself, if FILE is a symbolic link. String operators: -z STRING True if string is empty. -n STRING STRING True if string is not empty. STRING1 = STRING2 True if the strings are equal. STRING1 != STRING2 True if the strings are not equal. STRING1 < STRING2 True if STRING1 sorts before STRING2 lexicographically. STRING1 > STRING2 True if STRING1 sorts after STRING2 lexicographically. Other operators: -o OPTION True if the shell option OPTION is enabled. -v VAR True if the shell variable VAR is set. -R VAR True if the shell variable VAR is set and is a name reference. ! EXPR True if expr is false. EXPR1 -a EXPR2 True if both expr1 AND expr2 are true. EXPR1 -o EXPR2 True if either expr1 OR expr2 is true. arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne, -lt, -le, -gt, or -ge. Arithmetic binary operators return true if ARG1 is equal, not-equal, less-than, less-than-or-equal, greater-than, or greater-than-or-equal than ARG2. See the bash manual page bash(1) for the handling of parameters (i.e. missing parameters). Exit Status: Returns success if EXPR evaluates to true; fails if EXPR evaluates to false or an invalid argument is given.