web-dev-qa-db-fra.com

Le même script ouvert de trois manières différentes produit trois résultats différents. Pourquoi?

J'ai un exemple de script (le crédit va à kos ):

#!/bin/bash
cat <(cat /etc/lsb-release)

Je sauvegarde ce script sous le nom somename.sh dans mon répertoire personnel.

Maintenant, j'essaie d'ouvrir ce fichier de trois manières différentes:

sh somename.sh

bash somename.sh

./somename.sh

Donc, j'ai deux questions:

  1. Pourquoi les sorties des commandes ci-dessus sont-elles différentes alors qu'elles exécutent le même script?

    • sh produit une erreur de syntaxe

    • bash renvoie le résultat souhaité

    • ./ donne une erreur Permission Denied

  2. Pourquoi est-il nécessaire de donner au script une autorisation d'exécution uniquement lors de l'exécution du script avec ./ et non nécessaire dans les autres cas?

Merci d'avance!

EDIT: La première partie pourrait être similaire à la dupliquer liée mais j'avais aussi une deuxième question.

7
Raphael

Comme nous en avons discuté dans le chat:

  1. sh script génère une erreur car l'appel de l'interpréteur directement (dans ce cas, sh) ignore Shebang et le script est exécuté dans sh; sh ne prend pas en charge les substitutions de processus (<([...])), qui sont des bash-ismes, le script se ferme donc en cas d'erreur.

    bash script ne génère pas d'erreur car, même si Shebang est ignoré, le script est toujours exécuté dans Bash, qui prend en charge les substitutions de processus.

    ./script génère une erreur car script n'est pas exécutable.

  2. Pour exécuter un script avec ./ vous devez avoir le bit d'exécution pour votre utilisateur défini sur le script, il s'agit d'une contrainte du système d'exploitation.

    La question est donc: pourquoi bash script n'exige-t-il pas que le bit d'exécution soit défini pour votre utilisateur sur script?

    En effet, lors de l'exécution de bash script, le script est lu par Bash et Bash a le bit d'exécution défini pour votre utilisateur.

    Cela signifie que Bash, ayant l'autorisation d'exécuter du code, peut "contourner" la contrainte du système d'exploitation sur ce script, et tous les besoins de script doivent être lisibles par Bash.

8
kos
  • sh est un lien symbolique vers dash Shell et génère une erreur de syntaxe car il n'y a pas de syntaxe de <( . . .) dans sh. C'est seulement en bash (et en zsh et ksh si je me souviens bien).

  • bash affiche le résultat souhaité, car sa syntaxe est correcte, rien à redire

  • ./ donne une erreur Permission Denied parce que vous dites essentiellement "Hé, Shell, examinez les autorisations de ce fichier et examinez la première ligne (celle avec #!/bin/bash) dans mon répertoire actuel et comprendre comment exécuter ce script pour moi ". (note latérale: si le script se trouvait dans un emplacement inclus dans votre variable $PATH, il vous suffirait alors d'exécuter myScriptName.sh et le tour est joué, mais l'idée serait la même, nous devons vérifier exec autorisations et quel interprète utiliser)

Avant, vous utilisiez bash et dash et leur disiez de lire les commandes à partir d'un fichier. bash et dash sont exécutables cette fois, pas le script. Le script est maintenant source de commandes, un paramètre. Les autorisations de lecture sont toujours définies pour tous les utilisateurs, de sorte que les shells le liront.

5
Sergiy Kolodyazhnyy

En général, sh, ash, dash, bash, csh, tcsh, zsh... sont tous des coquilles avec leurs propres syntaxes et caractéristiques. Il y a quelques compatibilités mais elles sont orientées  [ 1 ]: un bash Shell exécutera un script sh mais il n'est pas dit que le vice-versa . Une invocation sh nécessite moins de ressources qu'une bash. Pour un seul cas, ce n'est pas un problème, pour des milliers, cela devrait être le cas.

Façons d'exécuter.
Pour exécuter un fichier sous forme de programme sous Linux, qu’il s’agisse d’un script ou d’un script compilé, vous devez définir le bit d’exécution [ 2 ] et il doit être inclus dans l’un des répertoires de votre _$PATH_.

Si c’est un script, il peut être passé comme argument au shell relatif (sh, bash..._myfile.whatever_): s’il est passé à Mauvais Shell vous pouvez obtenir un comportement incorrect et si vous êtes chanceux une erreur ; dans ce cas , il n’a pas besoin d’être exécutable car c’est comme si vous écriviez directement les lignes écrites dans le script dans le nouveau shell que vous appelez. Pour exécuter dans le même shell, vous pouvez utiliser plutôt _source myfile_ ou _. myfile_ équivalant à écrire ligne par ligne dans le shell actuel le contenu du script.

Emplacement
Si le programme exécutable n'est pas inclus dans votre chemin, vous devez spécifier où il peut être trouvé.

  • Dans votre cas, le ./ signifie uniquement le répertoire en cours de votre shell. _~/myfile.whatever_ doit également adresser le fichier _myfile.whatever_ dans votre répertoire personnel _~/_.
  • Vous pouvez l'invoquer depuis un autre emplacement, par exemple avec _/home/$USER/dir/myfile.whatever_.
  • Si ce fichier se trouve dans un répertoire inclus dans votre chemin, vous pouvez l'invoquer avec un simple _myfile.whatever_.

Dans le cas où plusieurs exécutables partagent le même nom, la spécification du chemin d'accès complet déterminera celui que vous allez exécuter. _which mycommand_ est capable de vous dire lequel sera exécuté maintenant (une fonction, un alias, un construit ou le premier trouvé dans votre chemin), mais il ne peut pas dire lequel sera exécuté ultérieurement ou à partir de un autre utilisateur. Si vous écrivez expressément le chemin complet, vous corrigerez cette ambiguïté. Il est utile d'exécuter une version spécifique d'un programme lorsque plusieurs versions sont installées simultanément ... et d'éviter les chevaux de Troie. Dans un script, il est toujours suggéré d'écrire _/bin/bash_ au lieu de bash.

3
Hastur