Chrooter apache
Matériel
Ajout disque dur
Ajout carte
Audit des disques durs
Gestion des peripheriques
Disquette d'installation
Ajout d'un scanner
Ajout d'une imprimante
Astuces
Astuces sous Linux
Réseau
Configuration reseau
Dns
Serveur cvs
Proxy squid 
Installation serveur ftp
Installation qmail 
Installation serveur courrier sous debian
Outil TCP/IP 
Le serveur samba
Connexion a distance securisee
Client/serveur vnc
Configurer apache
Dyndns
Installer un LAMP sous mandriva
Sécurité
Chiffrer un fichier/dossier
Securiser son poste
Mur pare feu pas a pas
Authentification ht-access
Surveillance de serveur CACTI
Snort
Snort-inline
Securiser Apache avec mod_security
Filtrage squid/squidguard/dansguardian
Auditer son site web
Sécuriser son linux
Installer un Lamp avec ssl
Contrer les scans de ports
Traitement anti-spam
Installer/Utiliser tripwire
Faire des sauvegardes incrémentales
Rsync
Nessus
Divers
Elisa, le multimédia facile
Utilisation de lilo
Les commandes Linux
Le multi-tache
Le crontab
Exploration de la configuration
Quotas
Messagerie
Installer une application
Debugger ses applications
Le format RPM
Mise a jour du noyau
Qemu
Tour d'horizon des principaux p2p
Récupération du système
Bips d'un pc
Astuces windows
Table Ascii
Lamerland
Conversion de fichiers musicaux
Compiler ses rpms
Graver en ligne de commande
Graver un fichier avi pour un dvd de salon
Récupérer des fichiers effacés
Gardez le contact avec Emesene
Liens
Notes php
hakin9
Secureroot.com
Hackerthreads.org
Defcon
Hackerlounge
Les derniers exploits
Tous les codes sources
Securite sous Linux
Les logiciels libres quotidiens
Ezine divers
Madchat
Textes divers
Archives
Tchat gratuit
 
Traductions LG
Toutes les traductions
Traductions Phrack
Toutes les traductions

Il y a actuellement 5 visiteurs connectés sur le site !

Google

Ecriture de script bash
Ecriture de script Ecriture de scripts bash

 

Introduction
Création et invocation d'un script
Creation d'un script
Invocation d'un script
Commentaires et tâches de fond
Valeur retournée par un shell-script à la fin de son execution
Commandes d'un shell-script
Commandes simples
Commandes composées
Commandes séquentielles
Le pipe
Commandes en paralleles
Commandes sur erreur
Commandes sur réussite
Commandes en paramètre
Utilisation des parentheses
Ecriture à l'ecran
Lecture au clavier
Commande select
Redirections des entrées-sorties standard
Variables et paramètres
Variables
Parametres
Calcul mathèmatique
Les structures conditionnelles
Les conditions
Les tests
Tests sur les entiers
Tests sur les chaines
Combinaison de tests
Structure Si...Alors...Sinon
Structure Répéter...Jusqu'à
Structure TantQue
A Autres structures exécutives
Structure Pour
Structure selon
Structure Lorsque
Fonctions

 

Comment :

Le shell est un interpréteur de commande qui sert d'interface entre l'utilisateur et le système d'exploitation. Bash est le plus utilisé des shells, c'est celui sur lequel nous nous baserons tout au long de ce chapitre. De plus, Bash est aussi un language de programmation complet visant à simplifier et automatiser les taches quotidiennes des administrateurs.

Creation et invocation d'un script

Creation d'un script

Un script, ou fichier de commandes, est un ensemble de commandes placées dans un fichier texte. Chaque ligne de ce fichier correspond à une ligne qu'aurait pu entrer un opérateur. Un script est destiné à un interpréteur qui lit, analyse, et exécute les commandes qu'il contient. Dans le cas d'un shell-script, l'interpréteur est un des shells d'Unix (bash, sh...). Dans ce document, nous allons apprendre à écrire un script en Bourne-shell (bash ou sh). La première ligne d'un script doit spécifier le programme à appeler pour l'interpréter. Elle doit commencer par la séquence "#!" suivie d'au moins une espace puis du nom de l'interpréteur.
Pour un shell-script écrit en Bourne-shell, elle sera :
#! /bin/bash
Pour un script Perl, la première ligne sera :
#! /usr/bin/perl
Le nom d'un shell-script peut être quelconque, mais on choisit généralement :
- soit "mon script" (sans extension), pour que son nom ait l'air d'une commande Unix comme une autre.
- soit "mon script.sh" pour indiquer explicitement qu'il s'agit d'un shell-script.

Invocation d'un script

On peut exécuter un script comme toute autre commande en l'appelant par son nom. Pour cela, il faut d'une part que les droits d'exécution soient positionnés correctements :
chmod +x mon_script
et, d'autre part, il faut que le chemin du fichier appartienne à la variable d'environnement PATH (sinon, vous devriez systématiquement préciser le chemin de votre script pour l'exécuter.
Une autre façon d'exécuter un script, et qui aboutit au même résultat, est d'invoquer son interpréteur avec le nom du script en paramètre (exemple : "sh mon script.sh").
Il faut savoir que, lancé ainsi, un script s'exécute dans un shell secondaire (sous-shell), totalement indépendant du shell qui l'a appelé Ceci aura pour effet d'annuler toute modification de l'environnement du script (changement de chemin avec cd, création ou modification de variables, etc...) dès lors que le script sera terminé.
Pour éviter cela, et donc permettre à un shell-script de modifier l'environnement de votre shell, il suffit d'appeler ce script grâce à la commande source (ou '.').
. mon_script
ou
source mon_script
Toutes les commandes du script sont alors exécutées dans le shell actuel.
Premier exemple de script
#! /bin/bash
echo hello world
Execution de notre script :
$ ./hello.sh
Hello world
Une autre facon de le lancer, cette fois-ci en appelant le script par l'interpreteur :
$ bash hello.sh
Hello World
Enfin de cette facon le script est lancé dans le shell en cours :
$ . hello.sh ou source hello.sh
Hello World

Commentaires et taches de fond

Chaque ligne commençant par un # ne sera pas traitée comme une commande mais comme un commentaire par le shell.
#! /bin/bash
#debut du script
echo hello world
#fin du script
De plus, toute commande suivie du caractère '&' s'executera en tâche de fond (arrière plan).

Valeur retournée par un shell-script a la fin de son execution

C'est la valeur retournée par la dernière commande exécutée dans le script. Par convention, une valeur de retour égale à 0 signifie que le script s'est bien déroulé. Inversement, toute autre valeur indique une erreur. De plus, on peut fixer cette valeur par la commande :
exit n
Dans ce cas, c'est n qui est retourné.
Comme pour toute commande, la valeur de retour d'un script peut être récupérée dans la variable $?.

Commandes d'un shell script

Commandes simples

Dans un script, on peut employer toute commande exécutable par l'utilisateur :
- un mot-clé appartenant au Bourne-shell (exemple : if, case, ...)
- une commande interne (builtin) au Bourne-shell (exemple : echo, umask,...)
- une fonction définie par l'utilisateur avec le mot-clé function
- une commande externe (commande appartenant aux chemins de la variable PATH).
Pour savoir d'où provient une commande, on peut utiliser type.

$ type while
while is a shell keyword
$ type cd
cd is a shell builtin
$ type lsc
lsc is aliased to 'ls -color=auto'
$ type mkdir
mkdir is /bin/mkdir

Commandes composées

Les exemples qui suivent sont donnés avec deux commandes mais peuvent être étendus à N commandes.

Commandes sequentielles

commande1 ; commande2
Exécute commande1 puis commande2.
Le point-virgule permet de réunir sur une seule ligne deux instructions qui devraient être sur deux lignes séparées. Lorsque c'est possible, son utilisation est à éviter puisqu'elle nuit à la lisibilité.

Le pipe

commande1 | commande2
Exécute commande1 et envoi le résultat à commande2.
Grâce au tube, commande2 effectue son traitement sur le texte qu'aurait affiché commande1.
Attention, commande1 et commande2 s'exécutent dans deux shells secondaires (sous-shells) et, par conséquent, toute modification qu'ils apportent à l'environnement (variables, chemin actuel,...) est perdue dès la fin de la commande.

Commandes en parallèles

commande1 & commande2
Exécute commande1 et commande2 en parallèles. commande1 est exécutée en tâche de fond.

Commande sur erreur

commande1 || commande2
Exécute commande2 si et seulement si commande1 a échouée ; généralement utilisé dans les conditions de structures de type if, while et until. .

Commandes sur réussite

commande1 && commande2
Exécute commande2 si et seulement si commande1 s'est bien déroulée. Généralement utilisé dans les conditions des structures if, while et until.

Commandes en paramètre

commande1 $(commande2) ou commande1 `commande2`
Cette combinaison exécute commande1 avec en paramètre le texte qu'aurait affiché commande2.
Exemple :
#! /bin/sh
#
# Shell-script de mise en application de la récupération du résultat
# d une commande. Affiche l'heure en français.
heures=$(date +%H)
minutes=`date +%M`
echo "Il est $heures heures $minutes minutes et $(date +%S) secondes"
$ ./heure
Il est 12 heures 29 minutes et 42 secondes
Les deux variantes proposées sont strictement identiques. On peux utiliser l'une ou l'autre pour des raisons de commodités.

Utilisation des parenthèses et des accolades

{ commande1 ; commande2; }, ( commande1; commande2 )
Les parenthèses et accolades permettent d'encadrer une série de commandes séparées les unes des autres par "&", "&&", "|", "||" ou " ;".
L'usage des parenthèses ou des accolades permet à l'ensemble des commandes qu'elles contiennent de subir une redirection. En effet, avec la commande "ls src ; ls bin | lpr", seul le contenu du répertoire bin est imprimé car une redirection ne s'applique qu'à la commande qui précède. Par contre, la commande " {ls src ; ls bin ; } | lpr" provoque bien l'impression du contenu des répertoires src et bin.
On préférera généralement les accolades aux parenthèses car les instructions situées entre parenthèses s'exécutent dans un shell secondaire indépendant du shell actuel (voir l'utilisation du tube, plus haut).
Attention, la dernière commande de la liste entre accolades doit être terminée par un point-virgule.

Ecriture

La commande "echo texte" permet d'écrire un texte à l'écran. Bien que ce ne soit pas nécessaire, pour éviter tout problème il est vivement conseillé d'encadrer le texte à afficher par des guillemets.
Si le texte à afficher est une chaîne vide, la commande provoque un saut de ligne.
L'option -n évite le saut de ligne automatique à la fin du texte.
L'option -e permet l'interprétation des caractères spéciaux utilisés avec printf(), tels l'alarme, le retour à la ligne, la tabulation, etc...
Exemples :

echo "Texte à
afficher"
echo ""
echo -n "Ce texte ne sera pas suivi d'un saut de ligne"
echo -e "\t\aCe texte commence par une tabulation et émet un signal sonore."

Lecture au clavier

La commande read utilisée seule permet de lire une phrase complète. La phrase lue est stockée dans la variable REPLY.
La commande "read mot1 mot2 reste" permet aussi de lire une phrase au clavier mais son premier mot est affecté à la variable mot1, son deuxième mot est affecté à mot2 et le reste de la phrase est affecté à la variable reste.
Exemple :
luser@localhost$ echo -n "Entrez votre nom de login et votre nom civil: "; read log nom
Entrez votre nom de login et votre nom civil: moliere Jean-Baptiste Poquelin
luser@localhost$ echo "$log est le nom de login de $nom"
moliere est le nom de login de Jean-Baptiste Poquelin
Attention : une opération du style "cat fichier | read ligne" ne fonctionnera pas car l'instruction read (tout comme l'instruction cat) sera exécutée dans un shell indépendant et le contenu de la variable ligne sera perdu dès la fin de l'opération. Par contre "read ligne < fichier" fonctionnera.

La commande select

La commande select permet d'offrir un menu à l'utilisateur. Sa syntaxe est :
select variable in "choix1" "choix2" ... "choixN"
do
liste d'instructions
done
Le menu présenté comporte l'ensemble des choix proposés précédés d'un numéro.
Une invite est affichée et le shell attend une entrée au clavier. La variable PS3 doit contenir la chaîne d'invite ("# ? " par défaut).
Lorsque l'utilisateur a entré son choix, le corps de la boucle est exécuté. La variable REPLY contient alors ce que l'utilisateur a rentré (un numéro normalement). Si le choix de l'utilisateur correspond à l'une des propositions qui lui sont faites, la variable "variable" contient aussi la chaîne correspondante ("choix1", "choix2", ... ou "choixN").
Exemple :

#! /bin/sh
#
# menu
#
# Shell-script de mise en application de l'instruction select.
PS3="Entrez le numéro de votre commande -> "
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." 1>&2
elif [ "$REPLY" -eq 1 ]; then
echo "Au revoir!"
break
else
echo "Vous avez fait le choix numéro $REPLY..."
echo "Votre $boisson est servi."
fi
echo
done
Test:
luser@localhost$ ./menu
Que désirez-vous boire ?
1) Rien, merci
2) Café
3) Thé au lait
4) Chocolat
Entrez le numéro de votre commande -> 3
Vous avez fait le choix numéro 3...
Votre Thé au lait est servi.
1) Rien, merci
2) Café
3) Thé au lait
4) Chocolat
Entrez le numéro de votre commande -> 1
Au revoir!
luser@localhost$

. Redirections des entrées-sorties standard

Avant tout, il faut savoir que toute redirection ne s'applique qu'à la dernière commande.
Dans le cas d'un série de commandes séparées par "&", "&&", "|", "||" ou " ;", si l'on veut que la redirection s'applique à l'ensemble des commandes, il faut employer des parenthèses (voir la partie "commandes composées").
L'entrée standard (stdin) peut être redirigée afin de lire dans un fichier plutôt qu'au clavier. Pour cela, placez "< fichier" en fin de commande. Exemple : pour lire la première ligne d'un fichier
luser@localhost$ read < mon_script; echo $REPLY
#! /bin/sh
luser@localhost$
La sortie standard (stdout) peut être redirigée afin d'écrire dans un fichier plutôt qu'à l'écran. Pour cela, placez "> fichier" ou ">> fichier" en fin de commande. Si l'opérateur ">>" est utilisé, le contenu actuel du fichier est conservé et le texte est ajouté en fin de fichier.
Exemple : Pour ajouter une ligne à la fin d'un fichier :
toto> echo "FIN DU FICHIER" >> fichier
toto>
La sortie standard d'erreur (stderr) peut être redirigée afin d'écrire dans un fichier plutôt qu'à l'écran. Pour cela, placez "2> fichier" en fin de commande.
Exemple :
Pour supprimer les messages d'erreur de l'affichage :
./ma_commande 2> /dev/null
La sortie standard et la sortie standard d'erreur peuvent être redirigées ensemble afin d'écrire dans un fichier plutôt qu'à l'écran. Pour cela, placez "&> fichier" en fin de commande.
Exemple :
Pour qu'une commande n'affiche rien, même pas les erreurs
ma_commande &> /dev/null &2" à la fin de la commande.
Exemple :
Pour afficher un message sur stderr plutôt que sur stdout :
echo "Erreur fatale, le disque est plein!" 1>&2
en ajoutant "2>&1" à la fin de la commande.
Exemple :
Pour afficher le résultat d'une commande page par page, y compris les erreurs :
ma_commande 2>&1 | more
L'entrée standard peut être lue depuis le shell-script en ajoutant "< Exemple :
Pour afficher plusieurs lignes de texte sans utiliser echo à chaque fois :
cat << FIN_DU_TEXTE
Vous êtes l'utilisateur $USER.
Vous êtes situé dans le répertoire $(pwd).
Merci de votre visite.
FIN_DU_TEXTE
La redirection par tube et l'emploi de l'expression "$(xxx)" ont déjà été décrits dans la partie "Commandes composées".

Variables et paramètres

Variables

Contrairement au DOS qui ne connaît que les variables d'environnement, les shells d'Unix font la distinction entre variables simples et variables d'environnement.
La différence entre les deux est que seules les variables d'environnement sont transmises aux programmes lancés depuis le shell (exception : lorsqu'on utilise le tube ou les parenthèses dans une commande composée, toutes les variables sont communiquées aux sous-shells qui sont lancés implicitement - par contre, ce qui suit reste valable).
La modification d'une variable n'est perçue que par le shell qui la modifie et par ses descendants (c'est-à-dire les commandes qu'il exécute) lorsque c'est une variable d'environnement.
Il s'ensuit qu'un script ne pourra jamais modifier les variables du shell courant, sauf s'il est appelé avec la commande source (voir plus haut "Invocation d'un script").
En Bourne-shell, définir une variable se fait par la commande : variable="valeur". Il est important que valeur soit spécifiée entre guillemets ou apostrophes, et qu'il n'y ait d'espaces ni avant ni après le signe '='. Si valeur est absente, la variable est créée mais contient une chaîne vide.
L'utilisation d'une variable se fait grâce à l'expression $variable ou ${variable}.
La deuxième notation est nécessaire si la variable est suivie d'un texte qui pourrait être interprété comme faisant partie du nom de la variable.
Exemple :

luser@localhost$ jour=10; mois=11; an=1997; heures=19; minutes=30
luser@localhost$ echo "Nous sommes le $jour/$mois/$an"
Nous sommes le 10/11/1997
luser@localhost$ echo "Il est ${heures}h ${minutes}mn"
Il est 19h 30mn
Définir une variable d'environnement se fait par la commande "export variable=valeur".
Transformer une variable en variable d'environnement se fait par la commande "export variable". Afficher la liste des variables d'environnement se fait par la commande "export". Afficher la liste complète des variables se fait par la commande "set". La commande "unset var" permet de détruire définitivement la variable var.
Au lancement du shell, beaucoup de variables sont prédéfinies, qu'elle soient d'environnement ou non. Par exemple, USER contient le nom de l'utilisateur, HOME contient le chemin de son répertoire personnel, etc... Pour en avoir la liste complète, faites "set" ou "export" dès le démarrage du shell, ou consultez le manuel en ligne de sh ("man sh" ou "man bash").
Sous Bourne-shell, certaines variables ont un sens spécial :
- $$ donne le numéro de processus (pid) du shell.
- $! donne le numéro de processus (pid) de la dernière commande lancée en tâche de fond (c'est-à-dire avec l'opérateur '&').
- $? donne la valeur retournée par la dernière commande.
- $ donne la liste des options avec lesquelles le shell a été appelé.

Paramètres

La variable $# donne le nombre de paramètres accompagnant l'appel du shell-script.
Les variables $@ et $* donnent l'ensemble des paramètres. La différence entre les deux termes ne s'observe que lorsqu'ils sont donnés entre guillemets. En effet, "$*" correspond à une seule valeur contenant tous les paramètres alors que "$@" correspond à autant de valeurs qu'il y a de paramètres.
On peut accéder à chaque paramètre en spécifiant son numéro après le signe $. Si le numéro tient sur deux chiffres ou plus, il doit être donné entre accolades.
Exemples :
$1, ..., $9, ${10}, ${11}, ...\ Le paramètre $0 correspond au nom complet (avec le chemin) du shell- script.
La commande "shift N" élimine les N premiers paramètres de la liste des paramètres (N ne doit pas être supérieur au nombre de paramètres). La variable $# est diminuée d'autant.
Après une commande shift, les paramètres sont donc décalés, c'est à dire que $1 prend la valeur de $(N1)+, $2 prend la valeur de $(N2)+, etc...
Exemple :
#! /bin/sh
#
# params
#
# Shell-script de mise en application des paramètres d'un script.
# Affiche l'ensemble des paramètres passés au script.
echo "Vous avez lancé
le shell-script $0"
echo "Vous lui avez fourni $# paramètres qui sont: $*"
echo ""
echo "Liste des paramètres :"
echo "----------------------"
numParam=1
for parametre in "$@"; do
echo "Paramètre $numParam = $parametre"
let $[numParam += 1]
done
echo ""
echo -n "Après la commande 'shift $#', "
shift $#
echo "il reste $# paramètres"
Test :
luser@localhost$ ./params A BC DEF "GH IJ"
Vous avez lancé le shell-script en lui fournissant les 4 paramètres qui sont: A BC DEF GHIJ:
luser@localhost$./params A BC DEF GHIJ
Liste des paramètres:
---------------------
Paramètre 1 = A
Paramètre 2 = BC
Paramètre 3 = DEF
Paramètre 4 = GH IJ
Après la commande 'shift 4', il reste 0 paramètres
luser@localhost$

Calcul mathématique

Le shell permet d'effectuer des calculs mathématiques mais uniquement sur des entiers. Il y a deux syntaxes possibles :
let $[ expression mathématique ]
let $(( expression mathématique ))
L'expression mathématique peut faire intervenir n'importe quelle variable (pas forcément précédée du signe $) ainsi que n'importe quel nombre entier décimal (219), hexadécimal (0xDB ou 16#DB), octal (0333 ou 8#333) ou binaire (2#011011011). Tous les opérateurs du langage C sont autorisés (+, -, *, %, ||, >>, =, +=, ^=, ==, !=, etc...), y compris les parenthèses.
On peut aussi utiliser la formulation "commande $[ expression mathématique ]". Dans ce cas, l'expression mathématique est remplacée par sa valeur puis la commande est exécutée.
Exemple :
luser@localhost$ echo $[ b % a ]
3
luser@localhost$ echo $[ a != 0 ]
1
luser@localhost$ echo $[ b > 20 ]
0
luser@localhost$ let $[ c = ( ( b + a ) << 4 ) & 0xFF ]
luser@localhost$ echo $c
144
luser@localhost$

Les structures conditionnelles

Les conditions

La condition d'exécution des structures conditionnelles qui suivent est qu'une commande aboutisse, c'est à dire que sa valeur de retour soit 0.
La commande qui sert de condition peut être une commande composée, en particulier on utilise souvent une formule du type "commande1 && commande2" ou "commande1 || commande2".
La condition peut être inversée si on fait précéder la commande d'un point d'exclamation.
Donc " ! commande" signifie que la condition est vraie si la commande échoue.
Attention, le point d'exclamation s'applique uniquement à la commande qui le suit ; pour qu'il s'applique à une commande composée, il faut l'encadrer avec des accolades (ou des parenthèses).
Exemples :
if commande; then echo "La commande a fonctionné"; fi
if ! commande; then echo "La commande a échoué"; fi
if commande1 && ! commande2; then \\ echo "commande1 a fonctionné mais pas commande2"; fi
if ! { commande1 || commande2; } ; then \ echo "Ni commande1 ni commande2 n'ont fonctionné"; fi

Les tests

La condition d'exécution devant être une commande, les tests s'effectuent par l'intermédiaire de la commande "test expression" qui peut être abrégée par la formule "[expression ]".
Les tests possibles peuvent porter sur des entiers, des chaînes de caractères ou des fichiers/répertoires.
Tests sur les fichiers (et sur les répertoires)
"-e fichier" : vrai si le fichier/répertoire existe.
"-s fichier" : vrai si le fichier à une taille supérieure à 0.
"-r fichier" : vrai si le fichier/répertoire est lisible.
"-w fichier" : vrai si le fichier/répertoire est modifiable.
"-x fichier" : vrai si le fichier est exécutable ou si le répertoire est accessible.
"-O fichier" : vrai si le fichier/répertoire appartient à l'utilisateur.
"-G fichier" : vrai si le fichier/répertoire appartient au groupe de l'utilisateur.
"-b nom" : vrai si nom représente un périphérique (pseudo-fichier) de type bloc (disques et partitions de disques généralement).
"-c nom" : vrai si nom représente un périphérique (pseudo-fichier) de type caractère (terminaux, modems et port parallèles par exemple).
"-d nom" : vrai si nom représente un répertoire.
"-f nom" : vrai si nom représente un fichier.
"-L nom" : vrai si nom représente un lien symbolique.
"-p nom" : vrai si nom représente un tube nommé.
"fichier1 -nt fichier2" : vrai si les deux fichiers existent et si fichier1 est plus récent que fichier2.
"fichier1 -ot fichier2" : vrai si les deux fichiers existent et si fichier1 est plus ancien que fichier2.
"fichier1 -ef fichier2" : vrai si les deux fichiers représentent un seul et même fichier.

Tests sur les entiers

Il y a erreur si ce ne sont pas des entiers autour de l'opérateur.
"entier1 -eq entier2" : vrai si entier1 est égal à entier2.
"entier1 -ge entier2" : vrai si entier1 est supérieur ou égal à entier2.
"entier1 -gt entier2" : vrai si entier1 est strictement supérieur à entier2.
"entier1 -le entier2" : vrai si entier1 est inférieur ou égal à entier2.
"entier1 -lt entier2" : vrai si entier1 est strictement inférieur à entier2.
"entier1 -ne entier2" : vrai si entier1 est différent de entier2.

Tests sur les chaines

Encadrer la chaîne par des guillemets !
"-n "chaîne"" : vrai si la chaîne n'est pas vide.
"-z "chaîne"" : vrai si la chaîne est vide.
""chaine1" = "chaine2"" : vrai si les deux chaînes sont identiques.
""chaine1" != "chaine2"" : vrai si les deux chaînes sont différentes.

Combinaison de tests

Lorsqu'un test doit être inversé ou lorsque plusieurs tests doivent être combinés par des ET et des OU, on a le choix entre deux notations. La première a été présentée dans la partie précédente ("Les conditions") ; elle est préférable car elle est plus lisible. La deuxième fait partie de la syntaxe de la commande test :
"NON expr" se traduit par "test ! expr" ou "[ ! expr ]".
"expr1 OU expr2" se traduit par "test expr1 -o expr2" ou "[ expr1 -o expr2 ]".
"expr1 ET expr2" se traduit par "test expr1 -a expr2" ou "[ expr1 -a expr2 ]".

Structure Si...Alors...Sinon

En Bourne-shell, la structure algorithmique se traduit par :
Si commande1 aboutit, alors if commande1; then action1
Sinon si commande2 aboutit, alors elif commande2; then action2
Sinon else action3 FinSi fi
Bien sûr, chacune des parties "sinon si" et "sinon" est optionnelle.
D'autre part les actions à effectuer peuvent être composées de plusieurs commandes sur une ou plusieurs lignes.
A l'extrême, on peut tout placer sur une seule ligne (bien respecter les points-virgules) mais c'est fortement déconseillé car cela nuit à la lisibilité :
if commande1; then action1; elif commande2; then action2; else action3; fi
Exemple :
#! /bin/sh
#
# signe
#
# Shell-script de mise en application de l'instruction if...then...else.
# Affiche le signe d'un nombre et de son opposé.
#
# Saisie de n
#
echo -n "Entrez un nombre: "
read n
#
# Test du signe de n
#
if test $n -lt 0; then # n < 0 ?
echo "Le nombre $n est négatif"
elif test $n -gt 0; then # n > 0 ?
echo "Le nombre $n est positif"
else # n = 0
echo "Le nombre $n est nul"
fi
#
# Changement du signe de n
#
let $[ n = -n ]
echo "Le nombre choisi devient $n"
#
# Test du signe de n (autre méthode)
#
if [ $n -le 0 ]; then # n <= 0 ?
if [ ! $n -eq 0 ]; then # n != 0 ? C'est à dire n < 0 ?
echo "Le nombre $n est négatif"
else # n = 0
echo "Le nombre $n est nul"
fi
else # n > 0
echo "Le nombre $n est positif"
fi
Test :
luser@localhost$ ./signe
Entrez un nombre: 3
Le nombre 3 est positif
Le nombre choisi devient -3
Le nombre -3 est négatif
luser@localhost$ ./signe
Entrez un nombre: 0
Le nombre 0 est nul
Le nombre choisi devient 0
Le nombre 0 est nul
luser@localhost$

Structure Répéter...Jusqu'à

Cette structure n'existe pas en Bourne-shell. Attention aux confusions, le mot-clé until est lié à une structure TantQue, comme on le voit dans ce qui suit.

Structure TantQue

En Bourne-shell, la structure algorithmique se traduit par :
TantQue commande aboutit while commande; do
action action
FinTQ done
TantQue commande échoue until commande; do
action action
FinTQ done
L'action à effectuer peut être composée de plusieurs commandes sur une ou plusieurs lignes.
A l'extrême, on peut tout placer sur une seule ligne (bien respecter les points-virgules) mais c'est fortement déconseillé car cela nuit à la lisibilité :
while commande; do action; done
until commande; do action; done
Exemple pour while :
#! /bin/sh
#
# factorielle
#
# Shell-script de mise en application de l'instruction while.
# Affiche la factorielle du nombre donné en paramètre.
if [ $# -ne 1 ] || [ $1 -lt 0 ]; then
echo "Usage: factorielle n (avec n >= 0)" 1>&2
else
resultat=1
n=$1
while [ $n -gt 1 ]; do
let $[ resultat *= n]
let $[ n -= 1]
done
echo "$resultat"
fi
Test:
luser@localhost$ factorielle 3
6
luser@localhost$ factorielle 6
720
luser@localhost$ factorielle $(factorielle 3)
720
Exemple : pour until
#! /bin/sh
#
# testfact
#
# Shell-script de mise en application de l'instruction until.
# Teste le shell-script de calcul de factorielles.
n=0
until [ $n -eq 14 ]; do
resultat=$(factorielle $n)
echo "$n! = $resultat"
let $[ n += 1 ]
done
Test:
luser@localhost$ ./testfact
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 1932053504
luser@localhost$

Autres structures exécutives

Structure Pour

Pour chaque élément de l'ensemble (element1, element2, ..., elementN) action sur element FinPour
En Bourne-shell, la structure algorithmique se traduit par :
for element in element1 element2 ... elementN; do
action $element
done
L'action à effectuer peut être composée de plusieurs commandes sur une ou plusieurs lignes.
A l'extrême, on peut tout placer sur une seule ligne (bien respecter les points-virgules) mais c'est fortement déconseillé car cela nuit à la lisibilité :

for element in element1 element2 ... elementN; do action $element; done
Exemple :
#! /bin/sh
#
# fic_ou_rep
#
# Shell-script de mise en application de l'instruction for.
# Affiche le type (fichier ou répertoire) de chaque paramètre.
for param in "$@"; do # Pour chaque paramètre...
if [ -f "$param" ]; then # C'est un fichier?
echo "$param est un fichier."
elif [ -d "$param" ]; then # C'est un répertoire?
echo "$param est un répertoire."
elif ! [ -e "$param" ]; then # N'existe pas
echo "$param n'existe pas."
else # C'est autre chose?
echo "$param n'est ni un fichier, ni un répertoire."
fi
done

Test :
luser@localhost$ ./fic_ou_rep XXX /etc "./un rep/" /etc/hosts "./un rep/un fic" /dev/lp0 XXX n'existe pas.
/etc est un répertoire.
./un rep/ est un répertoire
. /etc/hosts est un fichier.
./un rep/un fic est un fichier
. /dev/lp0 n'est ni un fichier, ni un répertoire.
luser@localhost$
Remarque : sous Unix, les espaces sont des caractères légaux (mais pas conseillés) dans les noms de fichiers et de répertoires. Sans les guillemets dans le script et sur la ligne de commande, "./un rep/" aurait été interprété comme deux mots distincts : "./un" et "rep/"

Structure Selon

En Bourne-shell, la structure algorithmique se traduit par :
Selon valeur case valeur in cas X : X )
action1 action1;;
cas Y :
cas Z : Y $|$ Z )
action2 action2;;
defaut : * )
action3 action3;;
FinSelon esac

Les actions à effectuer peuvent être composées de plusieurs commandes sur une ou plusieurs lignes. Pour chaque cas, la série de commandes à exécuter doit être terminée par deux points-virgules que l'on placera de préférence sur une seule ligne.
Les cas à tester peuvent employer les caractères génériques autorisés pour les fichiers.
Par exemple, les cas "a ? ? ?b", "A*B*C" et [a-z]*[0-9] sont tout à fait valides. Si toutefois un caractère fait partie d'un cas à tester, il faudra l'encadrer par des guillemets pour qu'il ne soit pas interprété.
Exemple :
#! /bin/sh
#
# question
#
# Shell-script de mise en application de l'instruction case.
# Pose une question et attend une réponse par oui ou non.
# La valeur retournée est 0 pour oui et 1 pour non.
retour=X
while [ "$retour" = "X" ]; do
echo -n "On continue (O/N) ? "
read reponse
case "$reponse" in
o* | O* )
retour=0
;;
[nN]* )
retour=1
;;
"?"* )
echo "Il n'y a pas d'aide disponible"
;;
* )
echo "Erreur : entrez [O]ui ou [N]on."
;;
esac
echo ""
done
exit $retour
Test :
luser@localhost$ question ; echo "Retour = $?"
On continue (O/N) ? bof
Erreur: entrez [O]ui ou [N]on
. On continue (O/N) ? oui, je veux bien
Retour = 0
luser@localhost$ question ; echo "Retour = $?"
On continue (O/N) ? ???
Il n'y a pas d'aide disponible
On continue (O/N) ? Non, merci
Retour = 1
luser@localhost$

Structure lorsque

Grâce à la commande trap, on peut déclencher une action sur un événement particulier.
La contrainte est que cet événement soit un signal que l'on peut intercepter (faire "trap -l" pour en avoir la liste et "man 7 signal" pour obtenir des détails supplémentaires sur ces signaux).
En Bourne-shell, la structure algorithmique se traduit par :
Lorsque le signal SIGNAL survient trap "action" SIGNAL action FinLorsque
L'action peut être une commande composée. Dès qu'elle ne se limite pas à un seul mot, elle doit être précisée entre guillemets. Les guillemets et apostrophes situés à l'intérieur doivent être précédés par un anti-slash. Bien sûr, plusieurs signaux peuvent être précisés en une seule fois.
La commande trap utilisée seule donne la liste des actions exécutées pour chaque signal.
La commande "trap SIGNAL" annule l'action à exécuter à l'arrivée du signal SIGNAL.
Exemple :
#! /bin/sh
#
# exTrap
#
# Shell-script de mise en application de l'instruction case.
trap "echo Le script s\'est terminé" EXIT
trap "echo Vous avez appuyé
sur Ctrl-C" SIGINT
trap "echo Vous avez fait: kill $$" SIGTERM
trap "echo J\'ai été
stoppé
et je continue" SIGCONT
trap "echo J\'ai rec?u SIGUSR1 ou SIGUSR2" SIGUSR1 SIGUSR2
echo "Processus $$: J'attend un signal..."
#
# Compte à rebours #
i=10
while [ $i -gt 0 ]; do
echo -n "$i "
sleep 1
let $[ i -= 1 ]
done
echo "0"
Test :
luser@localhost$ ./exTrap
Processus 1658: J'attend un signal...
10 9 Vous avez appuyé sur Ctrl-C
8 7
[1]+ Stopped exTrap
luser@localhost$ kill -SIGUSR1 1658
luser@localhost$ fg
exTrap
J'ai reçu SIGUSR1 ou SIGUSR2
J'ai été stoppé et je continue
6 5 4
[1]+ Stopped exTrap
luser@localhost$ kill -SIGUSR2 1658
luser@localhost$ kill 1658
luser@localhost$ fg
exTrap
J'ai reçu SIGUSR1 ou SIGUSR2
Vous avez fait: kill 1658
J'ai été stoppé et je continue
3 2 1 0
Le script s'est terminé
luser@localhost$

Fonctions

Le Bourne-shell offre la possibilité de définir ses propres fonctions. Bien qu'elles soient internes à un shell, elles s'emploient comme un script externe. Mais leur appel ne provoque pas le lancement d'un sous-shell, donc une fonction a accès à toutes les variables, pas seulement celles d'environnement, et leur modification reste prise en compte lorsque la fonction se termine.
Syntaxe
function maFonction()
{
local var1
local var2="valeur"
commande1
commande2
return val;
}
Le mot-clé "local" permet de définir des variables locales à la fonction.
La dernière commande doit être terminée par un point-virgule.
On accède aux paramètres d'une fonction comme à ceux d'un script : grâce aux variables $*, $@, $#, $1, $2, ... qui sont temporairement modifiées pendant toute la durée de la fonction. En revanche, $0 ne change pas.
Le retour d'une valeur s'effectue grâce au mot-clé return. Si return n'est pas employé, la valeur de retour est celle de la dernière commande exécutée.
Attention, l'emploi de la commande exit termine non seulement la fonction mais aussi le script.
Une fonction peut être récursive, c'est àdire qu'elle peut s'appeler elle-même.
Une fois définie, une fonction apparaît dans la liste des variables. On peut l'exporter vers les autres shells grâce à la commande "export -f maFonction".
Exemple :
#! /bin/sh
#
# signe2
#
# Shell-script de mise en application des fonctions.
# Affiche le signe d'un nombre et de son carré.
#
#
# carré(nombre)
#
# Retourne le carré du nombre donné en paramètre. #
# Paramètres: $1 -> Le nombre dont on veut le carré
#
function carré()
{
return $[ $1 * $1 ]
}
#
#
# affSigne(nombre)
#
# Affiche le signe du nombre donné en paramètre.
#
# Paramètres: $1 -> Le nombre dont on teste le signe.
#
function affSigne()
{
local signe
if [ $n -lt 0 ]; then # n < 0 ?
signe=négatif
elif [ $n -gt 0 ]; then # n > 0 ?
signe=positif
else # n = 0
signe=nul
fi
echo "Le nombre $1 est $signe"
}
#
#
# Programme principal
#
echo -n "Entrez un nombre: "
read n # Saisie de n
affSigne $n # Affichage du signe de n
carré
$n # Calcul du carré de n
n=$? # Récupération du résultat
echo "Le carré
du nombre choisi est $n"
affSigne $n # Affichage du signe de n

Test :
luser@localhost$ ./signe2
Entrez un nombre: -5
Le nombre -5 est négatif
Le carré du nombre choisi est 25
Le nombre 25 est positif
luser@localhost$ ./signe2
Entrez un nombre: 0
Le nombre 0 est nul
Le carré du nombre choisi est 0
Le nombre 0 est nul

Sources de l'article


 

Le Blog
Le blog
Le Forum
Le Forum
Php/Mysql
Formulaire en php
Administrer un serveur Mysql
Session en php
Gerer ses bases mysql
Les bases php
Securiser ses scripts PHP
Controler ses programmes avec RATS
Convertir une base sql en utf8
Astuces php
Le fichier php.ini
Programmation
Python rapide
Tutorial Python
Tutorial Perl
Tutorial Perl complet
Tutoriel ruby
Tutoriel C
Introduction à gawk
Filtres et utilitaires
Find
Programmation Shell
Ecriture de scripts bash
Expressions regulieres
Vi
Introduction a Javascript
Compiler avec gcc
Astuces en Bash
Cracking
Tutoriel Assembleur
Guide du cracking pour débutant
Assembleur
Manual Unpacking
Techniques de Protection
Différentes failles Web
Arp spoofing dans un réseau switché
Les intrusions
Les attaques externes
Defacage
Defacage complet
Buffer overflow
Netcat
Injection sql
Injection sql(suite)
John the Ripper
Spoofer un email
Utiliser google
La faille system
Usurper une identité
Le rooting
Shellcode sous Unix
La faille race condition
La faille xss
La faille xss (2)
Attaques sur un routeur
P2P
Azureus pas-a-pas
News
Lire les news de Linux-pour-lesnuls.com au format RSS
Distros
Gestion des paquets debian
101 commandes debian
Jeu
Webtarot
Graphisme
Effet neon dans GIMP
Effet vapeur dans GIMP
Cours fonctionnalités de GIMP
Redimentionner une image avec GIMP
Redimentionner une photo pour en faire un cadre avec gimp
Morphing avec gimp
Détourer avec gimp
Réduire le poids d'une image avec gimp
Caricature avec gimp
Eclairage avec gimp
Mettre en évidence avec gimp
Pluie sur le château
Créer une onde de surface avec Gimp
Un aspect satiné avec Gimp
Impacts de balle avec Gimp
Humour
Ensemble
Divers