Dlaczego ten softlink nie działa zgodnie z oczekiwaniami?


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#

Mój system operacyjny to fedora 24 (domyślna wersja GNOME).

Z przykładu możemy wiedzieć: under /bin, bashjest binarnym plikiem wykonywalnym; shto miękki link do bash.

Tak więc, o type bash and press enterile mi wiadomo, powinien mieć dokładnie taki sam wynik jak type sh and press enter.

Kiedy type bash and press enterdostaję [root@localhost bin]#zgodnie z oczekiwaniami.

Jednak jeśli ja type sh and press enter, to zaskakująco sh-4.3#.

Co jest przyczyną


Tekst, który można łatwo wkleić do edytora SE, ponieważ obraz jest dość irytujący, więc nie rób tego. Zamiast tego zaznacz tekst w swoim terminalu i naciśnij CTRL-SHIFT-C.
kot

Odpowiedzi:


25

To udokumentowana funkcja.

Jeśli uruchomisz bash za pomocą dowiązania symbolicznego sh, bash rozpocznie się w shtrybie zgodności.

Od man bash:

Jeśli bash jest wywoływany z nazwą sh, próbuje naśladować zachowanie startowe historycznych wersji sh tak dokładnie, jak to możliwe, przy jednoczesnym zachowaniu zgodności ze standardem POSIX. Wywoływany jako interaktywna powłoka logowania lub nieinteraktywna powłoka z opcją --login, najpierw próbuje odczytać i wykonać polecenia z / etc / profile i ~ / .profile, w tej kolejności. Opcji --noprofile można użyć do zahamowania tego zachowania. Wywoływany jako interaktywna powłoka o nazwie sh, bash szuka zmiennej ENV, rozszerza jej wartość, jeśli jest zdefiniowana, i używa rozszerzonej wartości jako nazwy pliku do odczytu i wykonania. Ponieważ powłoka wywoływana jako sh nie próbuje czytać i wykonywać poleceń z innych plików startowych, opcja --rcfile nie ma wpływu. Nieinteraktywna powłoka wywołana nazwą sh nie próbuje odczytać żadnych innych plików startowych. Wywołany jako sh, bash przechodzi w tryb posiksowy po odczytaniu plików startowych.

Skąd program wie, jakiej nazwy użyto do jego uruchomienia?

Jeśli jest to program ac, może to sprawdzić argv[0]. Jeśli jest to skrypt powłoki lub perla, może to sprawdzić $0.

Jako przykład rozważmy ten prosty skrypt powłoki:

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

$0to nazwa, z której skrypt został wywołany. ${0##*/}to nazwa wywołania skryptu z usuniętymi nazwami katalogów.

Stwórzmy to dowiązanie symboliczne:

ln -s utc et

Tak, utci etoba uruchomić ten sam plik wykonywalny ale zapewniają różne wyniki. Po uruchomieniu jako utcwyświetla czas uniwersalny. Po uruchomieniu jako et, wyprowadza czas wschodni USA. Na przykład:

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

4
Może warto dodać, jak to możliwe, ponieważ PO oczekuje, że połączenia będą identyczne. ( argv[0], obvs)
Lekkość

@LightnessRacesinOrbit Dobry pomysł. Dodałem przykład.
John1024,

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.