Shell script tips

De SeRoM - Wiki
Aller à : navigation, rechercher

READ

  • read sert à  initialiser des variable shell:
 $ read brol bidulle
 ceci est du bazard
 $ echo $brol
 ceci
 $ echo $bidulle
 est du bazard

Test

Numerique

  • 'test <num1> <eval-flag> <num2>'

note: <num> est soit un nombre, soit un -l <string> qui équivaut à  la longeur du string

tab of eval-flag

  • -eq : equal (=)
  • -ne : not equal (!=)
  • -lt : less than (<)
  • -le : less or equal (<=)
  • -gt : greater than (>)
  • -ge : greater or equal (>=)

Sting

  • test -z <$var> : test si la variable n'a pas encore été initialisée(true), ou si la longueur du string = zéro
  • test <$var> <eval> <$var> : compare les chaines

tab of eval

  • = : Vrai si les deux chaines sont identiques
  • != : Vrai si les deux chaines ne sont pas identiques
  • > : Vrai si la 1ere chaine est plus longue que la 2nd
  • < : Vrai si la 2nd chaine est plus longue que la 1ere

True / Flase

Les valeur de 'true' et 'false':

 [user@host]$ true
 [user@host]$ echo $?
  0
 [user@host]$ false
 [user@host]$ echo $?
  1

Fichier

  • test <eval-flag> <File>

tab of eval-flag

  • -G : Existe et appartient au même groupe que l'exécutant
  • -L : Existe et est un SoftLink
  • -O : Existe et appartient au même utilisateur que l'exécutant
  • -S : Existe et est un Socket
  • -b : Existe et est un fichier d'un Bloc Device
  • -c : Existe et est un fichier d'un char Device
  • -d : Est un Dossier
  • -e : Existe
  • -f : Existe et est un fichier regular
  • -g : ...
  • -r : Existe et possède les droits de lecture
  • -s : Existe et n'est pas un fichier vide
  • -u : ...
  • -w : Existe et possède les droits d'écriture
  • -w : Existe et possède les droits exécution
  • -ot : Fichier plus vieux (>< nt)

Combinaison logique

  • -a/-o &&/|| : Pour combiner deux conditions avec les opérateurs logiques AND ou OR
  • ! : Pour la négation

Boucles et conditions en Shell

IF

 if
 	[ -e file]
 then
 	command-block
 else
 	command-blok
 fi
 if
 	[ test ]
 then
 	command-block
 elif
 	[ test ]
 then
 	command-block
 else
 	command-blok
 fi

CASE

 case <string> in
 pattern)
 	command-block ;;
 pattern)
 	command-block ;;
 *)
 	command-block-by-default ;;
 esac

FOR

 for < var> in <list>
 do
 	command-block
 done

Exemples FOR

Compte de 1 à 15:

 for i in $(seq 1 15)
 do
 	echo ${i}
 	spleep 1
 done

Liste les fichier d'un directory:

 for file in $(ls -1 /my/dir)
 do
 	echo ${file}
 done

Lire le lignes d'un fichier

 IFS=$'\n'
 set -f
 for myLine in $(cat ./myFile); do
 	echo "${myLine}"
 done

WHILE

 while
 	[ test ]
 do
 	command-block
 done

Exemples WHILE

Lire le lignes d'un fichier

 while read myLine; do
 	echo "${myLine}"
 done < "./myFile"

Fonction

Déclaration

 name () { commands;}

Appel

 name param1 param2 ...

Variable

Par défaut, elles sont déclaré de facon global sauf indication contraire:

 UneFonction()
 {
 	#déclaration de la variable locale
 	local var=1
 }
 #Ici $var n'est plus reconnu

Tableaux

Initialisations

Plusieurs possibilités:

 tab[0]=Brol
 tab[1]=Bidule
 tab[2]=Truc
 tab[3]=Chose
 tab=([0]=Brol [1]=Bidule [2]=Truc [3]=Chose)
 tab=(Brol Bidule Truc Chose)

Attributs spéciaux

* ${nom_tableau[0]} : Donne le premier élément du tableau
* ${nom_tableau[@]} : Fait référence à tout les éléments du tableau. Utile pour une boucle for.
                                                 ( for i in "${nom_tableau[@]}" do [...] done )
* ${#nom_tableau[@]} : Donne la longueur du tableau

boucler dans un tableau

 tab=(Brol Bidule Truc Chose)
 
 for elem in ${tab[@]}
 do
     echo $elem
 done

Include

 #!/bin/sh
 . /path/to/MonFichierLib

Redirections

Redirige le standard output vers le nouveau fichier file (ou écrase le fichier si existant).

 > file
 1> file

Redirige le standard output vers le fichier file (complète le fichier).

 >> file

Redirige le standard error vers le nouveau fichier file.

 2> file

Redirige le standard output ET standard error vers le nouveau fichier file.

 &> file

De façon générale:

 <FileDesc> > <FileName>
 <FileDesc1> > &<FileDesc2>

On peut vouloir redirigé tout l'output d'un script ailleurs que sur la sortie standard. Typiquement un script qui est lancé via cron et pour lequel on ne veut pas recevoir de mail.

De rajouter en début de script une ligne du genre:

 exec > /dev/null
 exec &> /home/user/MonFichierCapture.out

Couleur

Un peu de couleur dans cette console de brute!

Cela fonctionne avec des balises:

  • \033<id-couleur>m : Balise pour commençant un couleur
  • [<?>;<??>m: ID Couleur
  • \033[m : balise de fermeture (reset le couleur initiale)

Ce qui nous donne:

  echo -e " Texte normal \033[0;32mTexte en vert\033[m Texte normal"

Un definition de variable peut donc etre pratique:

  # Definition des couleurs:
  ColorStart="\033"
  ColorStop="\033[m"
  ColorRed="[0;31m"
  ColorLightRed="[1;31m"
  ColorGreen="[0;32m"
  ColorLightGreen="[1;32m"
  ColorYellow="[0;33m"
  ColorLightYellow="[1;33m"
  ColorBlue="[0;34m"
  ColorLightBlue="[1;34m"
  ColorPink="[0;35m"
  ColorLightPink="[1;35m"
  ColorCyan="[0;36m"
  ColorLightCyan="[1;36m"
  ColorGray="[0;37m"
  ColorWhite="[1;37m"
  
  # Exemple d'utilisation
  echo -e "{ColorStart}${ColorRed}Texte en Rouge{ColorStop}"

Ou ce que j'ai l'habitude d'utiliser pour mes scripts pour mettre en évidence un status (OK | Error):

  # Definition des couleurs:
  START_COLOR_OK="\033[0;32m"
  START_COLOR_ERROR="\033[0;31m"
  STOP_COLOR="\033[m"
  OUT_OK="${START_COLOR_OK}Ok!${STOP_COLOR}"
  OUT_ERROR="${START_COLOR_ERROR}Error: ${STOP_COLOR}"
  
  # Exemple d'utilisation
  commande
  RET_CODE=$?
  case $RET_CODE in
          0)
                  echo -e "\t\t${OUT_OK}" ;;
          1)
                  echo -e "\t\t${OUT_ERROR}Message d'erreur";;
          *)
                  echo -e "\t\t${OUT_ERROR}Unknown Error!";;
  esac

Travail sur des fichiers

Lire un fichier ligne par ligne

 while read ligne  
 do  
    commande  
 done < fichier

Conventions et bonnes pratiques

Encapsulation des variables et des exec

Pour les variables ajoutons les accolades au dollar:

 ${variable}

Pour l'éxecution de commandes utilisons le 'dollar-parenthèses' en lieu et place des quote (`)

 $(commande)

Avantage

  • Plus de lisibilité
  • Moins de problème d'encapsulations (les parenthèses et accolades ont une indication de début/fin dont ne bénéficie pas une quote).
  • Possibilité d’exécuter des manipulations directement. Exemple manipulation de chaines directement dans les cruly-brackets
 echo ${var#pattern}           #Delete the pattern matched on the left
 echo ${var//pattern/replace}

Ref

Fichier temporaire

Utiliser la commande mktemp pour créer des fichiers temporaires:

 # On crée notre fichier temporaire
 workingFile=$(mktemp)
 # On travaile sur ce fichier
 myCommand > ${workingFile}
 ...
 # Et on n'oublie pas de le supprimer à la fin
 rm -rf ${workingFile}

La commande mktemp permet de générer des dossiers temporaires de la même façon avec l'option -d

Avantage

Plus de besoin de gérer les fichiers soi-même (et donc de devoir garantir l’unicité des fichiers par exemple).

Autres

Un bel article sur d'autres bonnes pratiques:

Arithmétique

Il est possible de faire de l’arithmétique. Il existe plusieurs méthodes pour cela.

BC

L'outil bc sert à interpréter les expressions mathématiques. Il est beaucoup plus pertinent que expr (gestion de nombres réels, syntaxe moins contraignante, plus de fonctions, ...)!

Exemple d'utilisation:

 echo "((1 + 1) * 3) / 2" | bc

Attention

Attention

Par défaut, bc exécute ses calculs en mode entier. Pour ne pas perdre l’approximation derrière la virgule, il faut définir la précision désirée. Avec scale on indique le nombre de chiffre après la virgule que l'on souhaite:

echo "scale=3; 10 / 3" | bc

Expr

C'est l'outil intégré au shell pour interpréter les expressions mathématique. Il est notamment appeler lors de l'usage de single quote ` `. Malheureusement cet outil est assez limité. Je préfère utiliser bc.

Awk

Exemple d'une commande awk qui lit et additionne chaque ligne d'un fichier qui contient un nombre par ligne:

 awk '{total += $NF} END {print total }' /tmp/numbers_only

L'utilisation de awk demande une page d'explication en soi. Vous en apprendrez donc sur la page qui va bien.

Quelques traitements de chaines

Upper/Lower case

tr

L'outil pour la conversion de chaine c'est tr! Voici comment il transforme la casse:

 echo ${varName} | tr '[:upper:]' '[:lower:]'           # upper --> lower
 echo ${varName} | tr '[:lower:]' '[:upper:]'           # lower --> upper

Bash v4

En Bash (mais uniquement à partir de la version 4 et supérieur), il existe une fonction de conversion de casse d'une variable:

 echo "${varName,,}"           # upper --> lower
 echo "${varName^^}"           # lower --> upper

Sed

On peut inverser la casse d'un bloque "matché" par des ( ). Exemple pour mettre une majuscule à la première lettre d'une chaine :

 echo "il manque une majuscule en début de ligne!" | sed -e 's/^\(.\)/\U\1/'

Ref:

Autres trucs en vrac

Envoyer un message sans NetCat

Quand nc (netcat) n'est pas installé ou pas disponible, on peut toujour se dérbouiller avec telnet pour envoyer un message sur un port:

 (sleep 1;  echo "Mon Petit Message" ;)| telnet <IP> <Port>

On peut même envisager d'établir une connexion sans avoir à utiliser expect:

 (sleep 2;
  echo ${userName};
  sleep 2;
  echo ${password}; 
  sleep 2;
  )| telnet ${IPAddres} ${Port}

À vous de définit les différentes variable préalablement (userName, password, IPAddres et Port).