Mise à jour : Debian 11.2 - Bullseye
Un script est un une séquence de commandes bash exécutable à partir d'un fichier texte
Sommaire
Les noms et extensions des fichiers scripts sont libres
La première ligne du script, commence par #! (shebang) et indique le shell à utiliser, dans le cas présent bash. La forme la plus portable est :
#! /usr/bin/env bash
Les lignes commençant par un # sont des lignes de commentaire
Les lignes ne commençant pas par un commentaire, sont interprétées comme des commandes de shell.
Exemple de fichier script :
$ cat démo
#! /usr/bin/env bash
# Ceci est une ligne de commentaire
echo "Test ok" # ceci est une ligne de commande
Un script peut-être lancé en ouvrant un nouvelle session bash
Soit avec la commande bash et le nom (ou chemin) du fichier passé en paramètre :
$ bash démo
test Ok
Soit directement, sans bash, après avoir rendu le fichier exécutable
$ chmod u+x démo
$ ./démo
test Ok
ou, sans indication du chemin si le script est dans le "PATH"
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
# mv démo /usr/local/bin/
$ démo
test OK
Un script peut-être lancé sans création d'une nouvelle session bash, avec la commande exec au lieu de bash, après avoir rendu le fichier exécutable. Toutefois, à la sortie du script, la session en cours est fermée.
$ bash
$ ps
PID TTY TIME CMD
2658 pts/0 00:00:00 bash
2677 pts/0 00:00:00 bash
2690 pts/0 00:00:00 ps
$ exec ./démo
Test ok
$ ps
PID TTY TIME CMD
2658 pts/0 00:00:00 bash
2691 pts/0 00:00:00 ps
Il est possible d'appeler un script depuis un script, sous réserve qu'il soit dans le même répertoire que le script appelant. L'inclusion s'effectue au moyen de la commande "source", suivie du chemin vers le script à inclure. La commande "source" peut-être remplacée par un point . , alias de la commande "source".
Dans l'exemple ci-dessous, les scripts script1 et script2 sont appelés à partir du script "principal"
Script appelant :
$ cat principal
#! /usr/bin/env bash
source "./script1"
source "./script2"
echo fin du script
Scripts appelés :
$ cat script1
#! /usr/bin/env bash
echo ceci est produit par le script1
$ cat script2
#! /usr/bin/env bash
echo ceci est produit par le script2
Exécution :
$ bash démo
ceci est produit par le script1
ceci est produit par le script2
fin du script
Un script peut-être lancé simultanément avec l'ouverture d'un chroot, en indiquant le chemin du script PAR RAPPORT au point de montage :
Exemple, lancement du script script_démo, dans le chroot monté en /mnt_chroot :
$ ls -l /mnt_chroot
.....
script_démo
....
# chroot /mnt_chroot ./script_démo
Lorsqu'un script est lancé avec les droits super-utilisateur, toutes les commandes sont effectuées avec les droits super-utilisateur.
Lorsqu'un script est lancé avec les droits utilisateurs, l'utilisation de sudo dans le script permet de lancer les commandes avec les droits super-utilisateur. Le mot de passe utilisateur sera demandé. On peut utiliser sudo -l en début de script :
$ sudo -l
[sudo] Mot de passe de xxxxx :
Entrées par défaut pour xxxxx sur buster :
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
L'utilisateur xxxxxx peut utiliser les commandes suivantes sur buster :
(ALL : ALL) ALL
Pour faire afficher les lignes de commande pendant l'exécution,
Soit lancer le script avec bash et l'option -x
$ bash -x démo
+ echo Test ok
Test ok
Soit utiliser, dans le script, la commande set -x pour débuter l'affichage des commandes à la ligne suivante, et set +x pour arrêter l'affichage à la ligne suivante :
$ cat démo
#! /usr/bin/env bash
set -x
# Ligne de commentaire
echo Test ok
$ ./démo
+ echo Test ok
Test ok
Le résultat de la dernière commande exécutée par le script est disponible dans le shell parent, dans le paramètre $? Lorsque la dernière commande s'est déroulée sans erreur, sa valeur est zéro :
$ ./démo
....
$ echo $?
0
Il est possible de donner une valeur numérique comprise entre 1 et 255 à $? avec la commande exit valeur :
$ cat démo
#! /usr/bin/env bash
exit 65
$ ./démo
$ echo $?
65
Les variables d'environnement sont disponibles dans le script :
$ var1=inconnu
$ export var2=connu
$ cat démo
#! /usr/bin/env bash
echo var1 est ....$var1
echo var2 est ....$var2
echo $HOME
Exécution
$ ./démo
var1 est ....
var2 est ....connu
/home/nom_utilisateur
Les variables créées dans un script ne sont pas disponibles dans le shell parent ;
$ cat démo
#! /usr/bin/env bash
variable_interne=test
echo $variable_interne
$ ./démo
test
$ echo $variable_interne
Les arguments passés au lancement du script sont utilisables dans le script comme paramètres de positionnement. Exemple :
$ cat démo
#! /usr/bin/env bash
echo Paramètre 1 : $1
echo Paramètre 2 : $2
echo Paramètre 3 : $3
echo Liste de paramètres: $@
echo Nombre de paramètres : $#
echo Nom du script : $0
Utilisation :
$ bash démo ceci est un test de paramètres
Paramètre 1 : ceci
Paramètre 2 : est
Paramètre 3 : un
Liste de paramètres: ceci est un test de paramètres
Nombre de paramètres : 6
Nom du script : démo
Les options (lettre ou chiffre précédé d'un tiret -) de la ligne de commande peuvent être analysées avec la fonction getotps:
$ cat demo
#! /usr/bin/env bash
while getopts "hv" Option; do
echo "Traitement de l'option $Option"
case $Option in
h) echo "Aide du script : blablabla"
;;
v) echo "Mode verbeux activé"
;;
?) echo "Cette option est inconnue"
;;
esac
done
$ ./demo -h
Traitement de l'option h
Aide du script : blablabla
$ ./demo -v
Traitement de l'option v
Mode verbeux activé
$ ./demo -x
./script_demo : option non permise -- x
Traitement de l'option ?
Cette option est inconnue
$ ./demo -vh -x
Traitement de l'option v
Mode verbeux activé
Traitement de l'option h
Aide du script : blablabla
./demo2 : option non permise -- x
Traitement de l'option ?
Cette option est inconnue
....
while getopts "h:v:" Option; do
...
$ cat demo2
#! /usr/bin/env bash
while getopts "h:v:" Option; do
echo "Traitement de l'option $Option"
echo "Argument $OPTARG"
case $Option in
h) echo "Aide du script : blablabla";;
v) echo "Mode verbeux activé";;
?) echo "Cette option est inconnue";;
esac
done
$ ./demo2 -h HELP -v VERBOSE
Traitement de l'option h
Argument HELP
Aide du script : blablabla
Traitement de l'option v
Argument VERBOSE
Mode verbeux activé
$ script.sh [options] ARG1 ARG2
$ cat script.sh
#! /usr/bin/env bash
# Traitement des options
while getopts "hu:" Option; do
case "$Option" in
h) echo Option h;;
u) echo Option u avec argument $OPTARG;;
esac
done
# Traitement des arguments positionnels
ARG1=${@:$OPTIND:1}
ARG2=${@:$OPTIND+1:1}
echo "Argument1 =$ARG1 Argument2 $ARG2"
$ ./test.sh -h -u test doc1 doc2
Option h
Option u avec argument test
Argument1 =doc1 Argument2 doc2
Pour utiliser un alias dans un script,
activer l'option correspondante (expand_aliases)
puis créer l'alias
#!/bin/bash
# 1 - Activation des alias :
shopt -s expand_aliases
# 2 - Création des alias, par exemple :
alias pingg='ping -c 3 google.fr'
$ cat demo.sh
#!/usr/bin/env bash
function bonjour {
echo "Bienvenue Monsieur $1"
}
bonjour titi
bonjour toto
$ ./demo.sh
Bienvenue Monsieur titi
Bienvenue Monsieur toto
Des fonctions peuvent être définies dans des scripts séparés qui seront lancés dans le script principal
Script contenant la fonction bonjour
$ cat fonction.sh
#!/usr/bin/env bash
function bonjour {
echo "******** bienvenue Monsieur $1 ******"
}
Script utilisant la fonction bonjour
$ cat demo.sh
#!/usr/bin/env bash
source"./fonction.sh"
bonjour $1
bonjour $2
$ ./demo.sh titi toto
******** bienvenue Monsieur titi ******
******** bienvenue Monsieur toto ******
Pour faciliter la recherche des erreurs dues à des caractères spéciaux orphelins ou non appairés (tels que parenthèses, crochets, double et simple quote, ..) orphelins, on peut s'aider de la commande suivante qui affiche les numéros des lignes contenant des nombres impairs d'un caractère donné :
$ tr -cd "\"\n" < nom_script | awk 'length%2==1 {print NR, $0}'
Remplacer le double quote \" par le simple quote '\ pour obtenir les lignes contenant un nombre impair de '
$ tr -cd "\(\n" < nom_script | awk 'length%2==1 {print NR, $0}'
$ tr -cd "\)\n" < nom_script | awk 'length%2==1 {print NR, $0}'
Par comparaison des numéros de ligne, on obtient les lignes dans lesquels le nombre de parenthèses diffèrent de 1 (ou 3 ou ...)
Procéder de même pour les crochets.
$ echo toto > fichier_test
$ sudo cat /dev/sdb1 > fichier_test
$ shasum - >> fichier_sha
$ echo toto | shasum -
$ sudo cat /dev/sdb1 | pv |shasum - |tee fichier_sha
Référence : How to fork/pipe stdin in bash script?
$ sudo cat /dev/sdb1 |sudo tee /dev/sdb2 |shasum -
$ seq 1 100 |tee >(grep 5 >file1) >(grep 6 >file2) >/dev/null
Exemple : réalisation sur le même flux de données, d'une copie sur un disque avec dd, du calcul de la checksum, du compte de nombre d'octets, ....
$ sudo dd if=/dev/sdb1 |tee >(sudo dd of=/dev/sdb2 skip=128) >(shasum - >fichier_sha) |wc -c
Attention à ce que plusieurs commandes n'utilisent pas simultanément vers la même sortie (fichier ou console). Les sorties seront enregistrées / affichées au fur et à mesure de leur arrivée et pourront donc être inexploitables.
echo -e "Première ligne \nDeuxième ligne
\tTroisième ligne avec tabulation"
$ Red='\033[0;31m'; Green='\033[0;32m'; Nocolor=
'\033[0m'
$ echo -e "Ceci_sans_couleur ${Red}Ceci en rouge ${Green}Ceci en vert ${Nocolor}Ceci_sans_couleur"
$ sleep 4.8 # Attend 4,8 secondes
$ read -p "Continuer? "
$ read -p "Continuer?" -t 5 # Attente 5 secondes maximum