Jump to content

Archived

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

P-A

[Tuto] Les Scripts Bash

Recommended Posts

C'est banal comme question, mais lorsque vous créez un script Bash est-il préférable d'utiliser:

#!/bin/sh

ou

#!/bin/bash

Après tout, quand on créé un script "bash" on veut que ça soit "bash" et non "Shell (sh)". Je sais que sh est un lien symbolique vers bash pour rétro-compatibilité, mais peut-on avoir des problèmes en spécifiant au script qu'il n'est que pour bash ?

Si nous utilisons des commandes dans le script qui ne sont valides qu'avec Bash et incompatible avec sh, tcsh, csh, ...

Share this post


Link to post
Share on other sites

tutuuut, sh -> bash, c'est valable uniquement sur linux, hein...

les *BSD ont bien un vieux sh tout pourri, tout comme OSX, solaris, and co :chinois:

donc si tu mets #!/bin/sh, risque d'y vaoir quelques petit problèmes de portabilité :p

Share this post


Link to post
Share on other sites

Tu charries un peu lorinc hein.

On précise l'interpréteur. Le sh (bourne shell) est installé de base dans pratiquement tous les unix qui par ailleurs se basent beaucoup sur des shell scripts.

Maintenant sh se fait un peu viellissant et a été remplacé par pas mal de shells (dont les plus connus sont bash et zsh) apportant plus de fonctionnalités pour l'utilisateur, mais aussi une plus grande souplesse de programmation.

Bash est le plus utilisé maintenant. zsh est pas mal utilisé aussi et semble avoir quelques fonctionnalités en plus (mais est un peu plus lourd quand même)

Ça c'est les faits.

Maintenant en pratique, il est vrai que sur certains unix viellissants il n'y a pas de bash (irix 6.5 solaris <=7, vielles distribs GNU/Linux), ce qui peut poser des problèmes de compatibilité. Mais en général, on peut assumer que bash est installé sur les systèmes récents (OpenBSD 3.9, cooker, dapper Drake, opensolaris...).

Donc sauf cas particuliers on peut utiliser du bash.

Share this post


Link to post
Share on other sites

Donc sauf cas particuliers on peut utiliser du bash.

Cas particulier comme FreeBSD ?

Share this post


Link to post
Share on other sites

si mais sh n'est pas un lien symbolique vers bash...

bash, c'est GNU, et GNU is Not Unix, en particulier pas BSD, donc...

FreeBSD possède ses propres outils non GNU et s'en sert par défaut :byebye:

Share this post


Link to post
Share on other sites

Je ne vois pas le problème.

Quand tu lance un #!/bin/bash, c'est exécuté par bash, ça ne change rien que sh soit ou non un lien symbolique ou pas.

Et chez debian, c'est en général un lien symbolique vers dash et pas bash.

Ensuite bash est porté sur les BSD. Libre à l'utilisateur de l'installer ou non.

Et les *sh sont supposés supporter la syntaxe bourne shell.

En gros tu as freebsd => Tu fais du ksh, du tcsh, du tout ce que tu veux, même du sh si tu veux, Si tu veux du bash ou du zsh rien ne t'empèche de l'installer.

Si tu as bash, tu peux faire tes scripts en bash.

Le seul truc qui peut changer, c'est si tu ne scripte plus pour toi, mais quand tu scriptes en pensant partager tes scripts et dans ce cas là soit tu sais que les destinataires auront le shell en question (j'ai dit bash parce que c'est le plus connu), soit tu fais du sh de base.

Share this post


Link to post
Share on other sites

Mise a jour du topic a 2h30 du matin, comme quoi c'est comme le baton de berger, y'a pas d'heure pour en manger ;p

Share this post


Link to post
Share on other sites

Sympa ce tuto justement je voulai me mettre au script shell mais je suis un peu perdu, quelle différence entre perl et script bash par exemple ?

Je dois faire un script de sauvegarde de repertoires d'une application (Zend) d'un serveur à un autre, puis un autre script qui me permettrait d'extraire l'archive sauvegardée du serveur A au serveur B, d'arreter l'application Oracle lié à Zend, Zend et Apache, renommer le dossier d'utilisation de Zend en cours en Zend.backup puis renommer le dossier de l'archive Zend.prod en Zend pour que mon application puisse redemarrer ... (j'espere que c'est a peu prés Français ce que j'ai mis :francais:)

Quelle solution opter ? Script bash ? Perl ? Je me demande vu que je sais pas bien faire la différence exacte entre les deux ...

Merci :francais:

Share this post


Link to post
Share on other sites

Bonjour,

J'écris en ce moment plein de scripts à la con qui servent à rien et que je met donc dans ~/scriptsUseless :)

J'aimerai rajouter ce dossier à la variable PATH dès que je me log en ssh.

j'ai rajouter dans ~/.bashrc:

export PATH=$PATH:$HOME/scriptsUseless

Donc c'est bien modifié quand je me logue en local mais pas quand je me logue en ssh :( Y'a-t-il une solution?

Est-ce qu'on peux modifier le message d'acceil d'ssh et y mettre quelque commande dedans? (genre pour modifier PATH :modoreussi: )

En considérant que j'ai 2 PC: Port et Serv,

Est-ce qu'on peux créer un script qui exécuter sur Port serai capable de lancer un programme sur un serveur X de Serv? (mhm pas sur d'être clair :s )

Share this post


Link to post
Share on other sites

Prends celui que tu maîtrise le mieux.

Les deux devront faire l'affaire.

Vu qu'il y a pas mal de commandes shell dans ton exemple, un script bash serait peut être plus approprié.

Sinon tu peux passer à perl si tu es trop limité par bash en lui même.

Share this post


Link to post
Share on other sites

Ok merci :modoreussi: Je maitrise aucun des deux c'est pour débuter et apprendre donc je vais commencer par les scripts shell avec bash puis je verrai par la suite peut etre pour perl !

Share this post


Link to post
Share on other sites
J'aimerai rajouter ce dossier à la variable PATH dès que je me log en ssh.

j'ai rajouter dans ~/.bashrc:

export PATH=$PATH:$HOME/scriptsUseless

Donc c'est bien modifié quand je me logue en local mais pas quand je me logue en ssh :( Y'a-t-il une solution?

Ton user a bien un bash par défaut ?

Tu peux vérifier si tu as quelque chose comme ça dans ton ~/.bash_profile :

if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

Est-ce qu'on peux modifier le message d'acceil d'ssh et y mettre quelque commande dedans? (genre pour modifier PATH :modoreussi: )
Pour le message d'accueil, tu peux voir ton /etc/motd. Pour le reste, voir plus haut.
En considérant que j'ai 2 PC: Port et Serv,

Est-ce qu'on peux créer un script qui exécuter sur Port serai capable de lancer un programme sur un serveur X de Serv? (mhm pas sur d'être clair :s )

Tu peux faire ça avec un ssh user@host commande

Et pour automatiser tu peux rajouter une ssh-keygen dans ton ~/.ssh/known_hosts

Share this post


Link to post
Share on other sites

Effectivement, il n'y avait pas de ~/.bash_profile ! Oo

Une fois rajouter avec le petit if qui va bien, ça marche! merci :)

Pour le message d'acceil, ça marche bien aussi :modoreussi:

Par contre pour le "log auto", il faut que je rajoute quoi dans ~/.ssh/known_hosts ?

Share this post


Link to post
Share on other sites

Là c'est plus compliqué, il faut le faire en plusieurs fois avec un fichier intermédiaire. (Ou peut être qu'il y a des options dans les dernières versions de sed ou de perl, à voir).

Share this post


Link to post
Share on other sites

hehe ben en voilà une nouvelle bonne idée de script à faire :yes:

bon ok, je retourne à mes tux, titi et toto :(

Share this post


Link to post
Share on other sites

Je voulais simplement ajouter une façon simple et rapide de créer une blacklist avec un script Bash et Iptables. Le blacklist se retrouve dans un fichier de texte brut (donc peut être facilement uploadé depuis une petite page en PHP si l'on veut mettre à jour, on ajoute un tâche CRON régulière (hourly ou daily) pour relancer le script).

Ajoutez ces lignes dans votre script de règles iptables que vous lancez probablement déjà depuis rc.local, juste après avoir établi les règles initiales (bloquer tout) et avant l'ouverture des ports publics:

IPT="/sbin/iptables"

for i in /etc/rc.d/blacklist.txt
do
 BANNED=`cat $i`
 for i in $BANNED
 do
$IPT -A INPUT -i eth0 -s $i -j DROP
 done
done

Et on ajoute ligne par ligne les adresses IP à bloquer dans blacklist.txt

* Faire attention de ne pas créer des blacklist trop longues, s'il y a plusieurs adresses utilisez des plages ou des réseaux entiers s'il le faut c'est plus efficace.

Share this post


Link to post
Share on other sites

J'avais écrit ça pour un topic, mais en fait c'était pas pour du shell classique mais pour du csh, du coup je met ça ici, il y a des parties qui sont aussi sur la première page, mais quelques petits trucs différents, on sait jamais, ça peut aider :

Donc on va partir du principe de base : le if.

Donc le if n'est pas une commande, mais un mot-clé (on ne peut donc pas utiliser if comme nom de programme, ou ce genre de choses).

La syntaxe (simplifiée) est la suivante (man bash) :

if list1; then list2; else list3; fi

list sont des listes d'instructions.

Le shell teste la valeur de retour de list1, si c'est bon ça exécute list2, sinon list3.

Alors la deuxième subtilité, c'est les valeurs de retour, en shell la valeur de retour d'un programme est un entier positif. Une valeur de 0 veut dire qu'il n'y a pas eu d'erreur ou de problème ("vrai"/"true") et les autres valeurs sont des codes d'erreur (qui peuvent avoir chacun un sens, c'est au choix de celui qui développe le logiciel).

Cette valeur n'est pas affichée dans le terminal, mais est également automatiquement stockée dans la variable $?.

Donc list1 peut être n'importe quel programme. Mais il y a de base des programmes qui servent presque uniquement à ça, par exemple true (/bin/true) et false (/bin/false) qui retournent respectivement 0 et 1.

true; echo "$?"

false; echo "$?"

if true; then echo "list2"; else echo "list3"; fi

Un autre programme vraiment plus intéressant est test, en paramètres de cette commande on met une expression qui peut être plus ou moins complexe.

Tout est expliqué dans man test, je vais prendre un petit exemple en utilisant l'option -e :

if test -e /bin/; then echo "list2"; else echo "list3"; fi

-e fichier permet de tester si fichier existe, si il existe, alors test retourne 0, sinon test retourne 1.

Enfin, si on regarde bien la man de test, on voit une syntaxe avec les caractères [ et ]. En fait, [ est également une commande (elle est dans /usr/bin/[ ). Elle marge exactement de la même manière que test, sauf qu'il faut mettre un ] comme dernier argument. C'est plus rapide à écrire, et ça rend plus joli.

Du coup, on peut transformer l'exemple précédent en :

if [ -e /bin/ ]; then echo "list2"; else echo "list3"; fi

Share this post


Link to post
Share on other sites
Quand tu lance un #!/bin/bash, c'est exécuté par bash, ça ne change rien que sh soit ou non un lien symbolique ou pas.

A ce propos, je préfère utiliser

#!/usr/bin/env bash

Comme ça le script tournera sans soucis si bash est dans le PATH mais pas dans /bin.

Sinon j'essaierai si j'ai le temps de faire un tuto sur les techniques un peu plus avancées du shell Unix (trap, les redirections, le contrôle du tty, les différences en sh/bash/ksh, les variables bash/ksh/sh, les substitutions, la gestion des jobs, etc.)

Je ferai un topic avec quelques tips que j'alimenterai au fur et à mesure.

Share this post


Link to post
Share on other sites
Mais pas si tu n'as pas env dans /usr/bin.

POSIX

Tu peux avoir un soucis par contre si ton /usr n'est pas monté (dans le cas ou il est sur une autre partition).

Share this post


Link to post
Share on other sites

J'ai vu plus d'OS qui n'avaient pas env dans /usr/bin que d'OS qui n'avaient pas bash dans /bin (quand ils avaient bash).

Share this post


Link to post
Share on other sites
J'ai vu plus d'OS qui n'avaient pas env dans /usr/bin que d'OS qui n'avaient pas bash dans /bin (quand ils avaient bash).

Ah? Lesquels? Perso j'ai testé /usr/bin/env en Solaris 8, Solaris 9,Solaris 10, AIX, HP-UX, debian et RHEL, et ça passe.

Share this post


Link to post
Share on other sites

×
×
  • Create New...