Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

variable PATH dans des scripts

94 réponses
Avatar
Kevin Denis
Bonjour,

je suis en train de mettre à jour différents scripts afin de les
adapter à différents environnements.

De manière générale (et c'est une question plus large), je vois
souvent des scripts démarrer par une définition des binaires utilisés,
comme par exemple:
#! /bin/sh
LS=/bin/ls
WC=/usr/bin/wc
echo le nombre de fichier est `LS|WC`

Ma première question est la suivante, pourquoi utiliser une définition
littérale alors que l'on peut utiliser PATH?
#! /bin/sh
PATH=/bin:/usr/bin
echo le nombre de fichier est `ls|wc`

Ma seconde question, plus spécifique à mon cas, puisque selon
l'architecture les binaires sont dans des lieux différents:
Mieux vaut il faire
#! /bin/sh
PATH=/opt/bin:/bin etc..

ou bien:
#! /bin/sh
if [ test archi ] then
LS=/bin/ls
else
LS=/opt/bin/ls
fi

etc..

Merci.
--
Kevin

10 réponses

1 2 3 4 5
Avatar
Kevin Denis
On 2008-05-26, Vincent Lefevre <vincent+ wrote:
Les scripts démarrent par une litanie de définitions, alors que
je me verrais plutôt faire un:
PATH=/bin:/usr/bin:/opt/v5/bin:/usr/v4/bin
et la, je suis sur d'appeler le bon binaire, au lieu de devoir
redéfinir selon le chemin, etc..
Je peux affiner si besoin est avec un
if [ version=5 ] then
PATH=...
else
PATH=...
fi


Pour des scripts que tu écris toi-même


oui.

et qui ne tourneront que sur
ta machine, c'est peut-être acceptable. Pour un script fourni par un
développeur d'une application qui devra tourner sur une multitude de
plateformes différentes,


non, il s'agit d'embarqué. J'ai la main (si je peux dire) sur le
système embarqué. L'utilisateur final ne touche pas au système,
il utilise le service fourni. Donc je suis capable de dire _a priori_
quel est l'environnement précis du système.

il en est tout autrement, et en général, il
suffit juste d'ajouter des répertoires en tête du $PATH. Mais ça peut
être plus compliqué si le script cherche à utiliser des ressources
fournies par le système (bibliothèques, Java, etc.) qui ne sont pas
forcément disponibles sans rien faire.

Ca m'interesse. Ca explique sans doute la raison (historique?) de fournir

les chemins complets.

Mais le fait que je voie énormément de script appeler chaque
binaire par leur chemin me fait douter de ma méthode.

En forçant un PATH en début de script au lieu de définir le chemin
complet de chaque binaire, est ce que je risque un problème? Lequel?


Dans certains cas, utiliser le chemin complet (une fois déterminé
au début) peut être plus rapide.


ok.

C'est ce que font les autotools,
car certains utilitaires sont exécutés très souvent. En effet, si
un utilitaire se situe loin dans le $PATH, ça peut prendre du temps
au shell de le rechercher à chaque fois, surtout s'il y a du NFS.
Certains shells ont un système de cache, mais pas tous (d'autant
plus que le système de cache a ses inconvénients).

Ok.


Donc, de manière générale, il est intéressant de définir le chemin
complet de chaque binaire plutôt que de définir un PATH pour des
raisons de mise en cache ou de rapidité.

Dans mon cas, particulier, je vais utiliser la méthode $PATH.
--
Kevin


Avatar
Paul Gaborit
À (at) 26 May 2008 11:26:47 GMT,
Nicolas George <nicolas$ écrivait (wrote):
Vincent Lefevre wrote in message
<20080526111452$:
Par exemple, il y a des bibliothèques qui
ont le même nom, mais qui sont incompatibles


Ce n'est absolument pas normal. Ton système est cassé.


C'est marrant ça. Depuis presque vingt ans que j'utilise différents
Un*x, je ne m'étais jamais aperçu que ces différents systèmes étaient
tous cassés ! ;-)

Plus sérieusement, lorsqu'on utilise des softs propriétaires qui
exigent telles ou telles version de telles ou telles bibliothèques, on
n'a pas le choix ni du nom ni de la version. On est alors obligé des
faire ce genre de bidouilles. Ok, en principe, ce n'est pas très
propre mais parfois on n'a vraiment pas le choix.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>


Avatar
Nicolas George
Paul Gaborit wrote in message :
Ok, en principe, ce n'est pas très
propre


Merci de ton soutien.

Avatar
Paul Gaborit
À (at) 26 May 2008 12:45:23 GMT,
Nicolas George <nicolas$ écrivait (wrote):
Paul Gaborit wrote in message :
Ok, en principe, ce n'est pas très
propre


Merci de ton soutien.


...qui ne durait pas plus loin que le milieu de ma phrase ! ;-)

C'est donc un soutien théorique (ou de principe) mais pas un soutien
pratique (je reste pragmatique).

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>


Avatar
Stephane CHAZELAS
2008-05-26, 11:13(+00), Vincent Lefevre:
[...]
Mais le fait que je voie énormément de script appeler chaque
binaire par leur chemin me fait douter de ma méthode.

En forçant un PATH en début de script au lieu de définir le chemin
complet de chaque binaire, est ce que je risque un problème? Lequel?


Dans certains cas, utiliser le chemin complet (une fois déterminé
au début) peut être plus rapide. C'est ce que font les autotools,
car certains utilitaires sont exécutés très souvent. En effet, si
un utilitaire se situe loin dans le $PATH, ça peut prendre du temps
au shell de le rechercher à chaque fois, surtout s'il y a du NFS.
Certains shells ont un système de cache, mais pas tous (d'autant
plus que le système de cache a ses inconvénients).


Tous les shells standard Unix ont ce cache et la commande "hash"
qui va avec (c'est une "XSI extension" dans SUSv3).

Et parmi les shells POSIX que je connais, il n'y a que posh qui
ne le supporte pas.

Et si a premiere vue (en regardant le code source), le Bourne
shell de Unix V7 n'avait pas de tel cache, la commande "hash" a
ete ajoutee dans SVR2 et peut-etre que le caching a ete
introduit avant ca.

Autant dire qu'il faut se lever tot pour trouver un shell qui
n'a pas de tel cache (surtout sur un systeme qui supporte NFS).

Dans tous les cas, je ne trouve pas que ce soit un bon argument.
Grapiller de la performance au detriment de la maintainabilite
est une erreur.

A mon avis, hardcoder le chemin de commandes devrait etre limité
au minimum. Si PATH doit etre modifié, plutot ajouter les
repertoires a la fin qu'au debut, ca laisse la possibilité a
l'administrateur/utilisateur de definir quel est le PATH correct
pour les commandes standard.

Maintenant, il y a des tas de cas pratique ou on voudra modifier
PATH et eventuellement hardcoder certains chemins quand PATH ne
peut pas resoudre tous les problemes.

Mais si on a le controle du systeme, le mieux est de ne rien
hardcoder du tout bien sur.

--
Stéphane


Avatar
Vincent Lefevre
Dans l'article <483aa258$0$19301$,
Nicolas George <nicolas$ écrit:

Vincent Lefevre wrote in message
<20080526113449$:

Même nom, deux bibliothèques incompatibles.


Je maintiens : si elles sont incompatibles, qu'elles aient le même
nom est un bug, il n'y a pas d'autre nom.


Appelle cela comme tu veux, mais c'est la réalité, et le monde vit
très bien avec. Je suppose que ce choix a été fait parce que les
outils de compilation des programmes (style autoconf) cherchaient
readline, mais pas editline (qui a la même API); d'ailleurs
/usr/lib/libreadline.dylib est un lien symbolique vers libedit.dylib.
La source du problème est dans le design des outils de compilation,
qui se basent sur des noms de fichiers au lieu des fonctionnalités
apportées (e.g. API).

Le même genre de chose est fait avec ncurses, qui fournit des liens
de compatibilité avec curses.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)


Avatar
Vincent Lefevre
Dans l'article ,
Stephane CHAZELAS écrit:

Tous les shells standard Unix ont ce cache et la commande "hash"
qui va avec (c'est une "XSI extension" dans SUSv3).


Ce n'est pas ce que je vois avec le /bin/sh sous Linux (c'est bash,
mais exécuté en tant que sh):

ay:~> bash
:~$ ls foo
ls: cannot access foo: No such file or directory
:~$ ln -s /bin/true bin/ls
:~$ ls foo
ls: cannot access foo: No such file or directory
:~$ rm bin/ls
rm: remove symbolic link `bin/ls'? y
:~$ exit
ay:~> sh
sh-3.1$ ls foo
ls: cannot access foo: No such file or directory
sh-3.1$ ln -s /bin/true bin/ls
sh-3.1$ ls foo
sh-3.1$ rm bin/ls
sh-3.1$ exit

Dans le premier cas (bash exécuté en tant que bash), le shell ne voit
pas le nouveau ls (dans un répertoire situé avant dans le $PATH) à
cause du cache. Dans le second cas (bash exécuté en tant que sh), le
shell voit le nouveau ls, donc pas de cache.

C'est d'autant plus important que les scripts shell portables
commencent par #!/bin/sh et non #!/bin/bash, et que $SHELL vaut
généralement /bin/sh.

Dans tous les cas, je ne trouve pas que ce soit un bon argument.
Grapiller de la performance au detriment de la maintainabilite
est une erreur.


Je suis d'accord, mais je pense qu'autoconf le fait correctement;
en gros, il implémente lui-même le système de cache en cherchant
la commande dans le $PATH puis en conservant la position pour le
reste du script.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

Avatar
Vincent Lefevre
Dans l'article <483aa2da$0$19301$,
Nicolas George <nicolas$ écrit:

Vincent Lefevre wrote in message
<20080526113210$:
Il n'y a pas forcément un environnement unique qui convienne à tout
le monde.


Il y a presque toujours un environnement qui convienne à la plupart des
scripts lancés sur une machine. Que cet environnement soit dupliqué dans
chacun des scripts est totalement contre-productif et crétin.


Et c'est pour ça que la plupart des scripts de /etc/init.d sous Debian
(pour prendre un exemple) fixent le $PATH... Debian contre-productif et
crétin?

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)


Avatar
Nicolas George
Vincent Lefevre wrote in message
<20080527005221$:
Appelle cela comme tu veux, mais c'est la réalité, et le monde vit
très bien avec. Je suppose que ce choix a été fait parce que les
outils de compilation des programmes (style autoconf) cherchaient
readline, mais pas editline (qui a la même API); d'ailleurs
/usr/lib/libreadline.dylib est un lien symbolique vers libedit.dylib.
La source du problème est dans le design des outils de compilation,
qui se basent sur des noms de fichiers au lieu des fonctionnalités
apportées (e.g. API).


Sur un système correctement conçu, ce n'est pas un problème : on peut très
bien compiler un programme avec « -lreadline » et obtenir un binaire qui
dépend ensuite de libeditline.so.42. C'est précisément à ça que sert le
SONAME.

Après, si tu es en train de me dire que macos x est mal conçu, au fond je
n'en serais pas surpris, hein.

Mais sous un vrai Unix bien conçu, GNU ou BSD pas charcuté par apple, ça
marche très bien. Et il n'y a pas besoin de variables d'environnement pour
que les applications retrouvent leurs petits.

Le même genre de chose est fait avec ncurses, qui fournit des liens
de compatibilité avec curses.


ncurses est binairement compatible avec curses.

Avatar
Stephane CHAZELAS
2008-05-27, 01:37(+00), Vincent Lefevre:
Dans l'article <483aa2da$0$19301$,
Nicolas George <nicolas$ écrit:

Vincent Lefevre wrote in message
<20080526113210$:
Il n'y a pas forcément un environnement unique qui convienne à tout
le monde.


Il y a presque toujours un environnement qui convienne à la plupart des
scripts lancés sur une machine. Que cet environnement soit dupliqué dans
chacun des scripts est totalement contre-productif et crétin.


Et c'est pour ça que la plupart des scripts de /etc/init.d sous Debian
(pour prendre un exemple) fixent le $PATH... Debian contre-productif et
crétin?


Ben justemement, pour que PATH soit correct pour les scripts
des utilisateurs, il faut bien que quelquechose dans le systeme
le definisse. Et c'est en general les init scripts.

Typiquement, le PATH que les cron jobs heritent est le PATH
definit dans /etc/init.d/cron ou un de ses ancetres.

Maintenant, il y a aussi:
- le PATH des utilisateurs normaux,
- le PATH des super-utilisateurs quand ils se logguent
- le PATH de cron
- le PATH de xinetd/inetd
- le PATH par default du systeme
- le PATH de compatibilite avec tel ou tel standard (par
exemple, sous Solaris, faut faire un "getconf PATH" dans le
bon environnement (gueh!?) pour avoir des outils conformes
sinon par defaut on a les outils des 1980s.

C'est pas forcement toujours rose et propre.

--
Stéphane



1 2 3 4 5