Pourquoi ce lien logiciel ne fonctionne-t-il pas comme prévu?

11
bash4.3 # pwd
/bin
bash4.3 # ll sh
lrwxrwxrwx. 1   root    root    4   May 17 22:22 sh -> bash
bash4.3 # ll bash
-rwxr-xr-x. 1   root    root    1072056 May 17 22:22 bash
bash4.3 # bash
bash4.3 # sh
sh-4.3#

Mon OS est fedora 24 (version GNOME par défaut).

D'après l'exemple, nous pouvons savoir: under /bin, bashest un exécutable binaire; shest un lien logiciel vers bash.

Donc, à ma connaissance, type bash and press enterdevrait avoir exactement le même résultat type sh and press enter.

Quand je type bash and press enter, je reçois [root@localhost bin]#comme prévu.

Cependant, si je le fais type sh and press enter, je l'obtiens étonnamment sh-4.3#.

Quelle en est la cause?

xmllmx
la source
Le texte qui pourrait facilement être copié-collé dans un éditeur SE en tant qu'image est assez ennuyeux, alors ne le faites pas. Au lieu de cela, sélectionnez le texte dans votre terminal et appuyez sur CTRL-MAJ-C.
cat

Réponses:

25

C'est une fonctionnalité documentée.

Si vous exécutez bash via un lien symbolique nommé sh, bash démarrera en shmode de compatibilité.

De man bash:

Si bash est appelé avec le nom sh, il essaie d'imiter le comportement de démarrage des versions historiques de sh aussi fidèlement que possible, tout en se conformant également à la norme POSIX. Lorsqu'il est appelé en tant que shell de connexion interactif ou shell non interactif avec l'option --login, il essaie d'abord de lire et d'exécuter des commandes à partir de / etc / profile et ~ / .profile, dans cet ordre. L'option --noprofile peut être utilisée pour inhiber ce comportement. Lorsqu'elle est invoquée en tant que shell interactif avec le nom sh, bash recherche la variable ENV, développe sa valeur si elle est définie et utilise la valeur développée comme nom d'un fichier pour lire et exécuter. Puisqu'un shell appelé comme sh n'essaye pas de lire et d'exécuter des commandes à partir d'autres fichiers de démarrage, l'option --rcfile n'a aucun effet. Un shell non interactif appelé avec le nom sh n'essaie pas de lire d'autres fichiers de démarrage. Lorsqu'il est appelé en tant que sh, bash entre en mode posix après la lecture des fichiers de démarrage.

Comment un programme sait-il quel nom a été utilisé pour le démarrer?

S'il s'agit d'un programme alternatif, il peut inspecter argv[0]. S'il s'agit d'un script shell ou perl, il peut l'inspecter $0.

À titre d'exemple, considérons ce script shell simple:

$ cat utc
#!/bin/sh
case "${0##*/}" in
        utc) date -u ;;
        et) TZ=US/Eastern date ;;
esac

$0est le nom par lequel le script a été appelé. ${0##*/}est le nom que le script a été appelé sans aucun nom de répertoire.

Créons ce lien symbolique:

ln -s utc et

Ainsi, utcet les etdeux exécutent le même exécutable mais ils fournissent des résultats différents. Lorsqu'il est exécuté en tant que utc, il génère un temps universel. Lorsqu'il est exécuté en tant que et, il affiche l'heure de l'Est américain. Par exemple:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016
John1024
la source
4
Pourrait ajouter comment cela est possible, car l'OP s'attend à ce que les appels soient identiques. ( argv[0], obvs)
Courses de légèreté en orbite
@LightnessRacesinOrbit Bonne idée. J'ai ajouté un exemple.
John1024
Parfait maintenant. :)
Courses de légèreté en orbite