Warum funktioniert dieser Softlink nicht wie erwartet?


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#

Mein Betriebssystem ist Fedora 24 (Standard-GNOME-Version).

Aus dem Beispiel können wir wissen: unter /bin, basheine ausführbare Binärdatei ist; shist ein weicher Link zu bash.

Meines Wissens type bash and press entersollte also genau das gleiche Ergebnis erzielt werden wie type sh and press enter.

Wenn ich type bash and press enter, bekomme ich [root@localhost bin]#wie erwartet.

Wenn ich es jedoch type sh and press enterbekomme, bekomme ich es überraschend sh-4.3#.

Was ist die Ursache?


Text, der leicht als Bild in einen SE-Editor kopiert werden kann, ist ziemlich ärgerlich. Tun Sie dies also bitte nicht. Wählen Sie stattdessen den Text in Ihrem Terminal aus und drücken Sie STRG-UMSCHALT-C.
Katze

Antworten:


25

Das ist eine dokumentierte Funktion.

Wenn Sie bash über einen Symlink mit dem Namen ausführen sh, wird bash im shKompatibilitätsmodus gestartet .

Von man bash:

Wenn bash mit dem Namen sh aufgerufen wird, wird versucht, das Startverhalten historischer Versionen von sh so genau wie möglich nachzuahmen und dabei auch dem POSIX-Standard zu entsprechen. Beim Aufruf als interaktive Anmeldeshell oder als nicht interaktive Shell mit der Option --login wird zunächst versucht, Befehle aus / etc / profile und ~ / .profile in dieser Reihenfolge zu lesen und auszuführen. Die Option --noprofile kann verwendet werden, um dieses Verhalten zu verhindern. Beim Aufrufen als interaktive Shell mit dem Namen sh sucht bash nach der Variablen ENV, erweitert ihren Wert, wenn sie definiert ist, und verwendet den erweiterten Wert als Namen einer Datei zum Lesen und Ausführen. Da eine als sh aufgerufene Shell nicht versucht, Befehle aus anderen Startdateien zu lesen und auszuführen, hat die Option --rcfile keine Auswirkung. Eine nicht interaktive Shell, die mit dem Namen sh aufgerufen wird, versucht nicht, andere Startdateien zu lesen. Wenn bash als sh aufgerufen wird, wechselt es in den Posix-Modus, nachdem die Startdateien gelesen wurden.

Woher weiß ein Programm, mit welchem ​​Namen es gestartet wurde?

Wenn es sich um ein Wechselstromprogramm handelt, kann es es überprüfen argv[0]. Wenn es sich um ein Shell- oder Perl-Skript handelt, kann es überprüft werden $0.

Betrachten wir als Beispiel dieses einfache Shell-Skript:

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

$0ist der Name, unter dem das Skript aufgerufen wurde. ${0##*/}ist der Name, unter dem das Skript aufgerufen wurde, wobei alle Verzeichnisnamen entfernt wurden.

Lassen Sie uns diesen Symlink erstellen:

ln -s utc et

Also, utcund etbeide führen dieselbe ausführbare Datei aus, liefern aber unterschiedliche Ergebnisse. Bei Ausführung als utcgibt es die Weltzeit aus. Bei Ausführung als etwird die US-Ostzeit ausgegeben. Beispielsweise:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016

4
Vielleicht möchten Sie hinzufügen, wie dies möglich ist, da das OP erwartet, dass die Anrufe identisch sind. ( argv[0], obvs)
Leichtigkeitsrennen im Orbit

@ LightnessRacesinOrbit Gute Idee. Ich habe ein Beispiel hinzugefügt.
John1024

Perfekt jetzt. :)
Leichtigkeitsrennen im Orbit
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.