Perché questo softlink non funziona come previsto?


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#

Il mio sistema operativo è fedora 24 (versione GNOME predefinita).

Dall'esempio, possiamo sapere: sotto /bin, bashè un eseguibile binario; shè un collegamento soft a bash.

Quindi, per quanto ne so, type bash and press enterdovrebbe avere lo stesso risultato esattamente come type sh and press enter.

Quando ottengo type bash and press enter, [root@localhost bin]#come previsto.

Tuttavia, se io type sh and press enter, sorprendentemente ottengo sh-4.3#.

Qual è la causa?


Il testo che potrebbe essere facilmente copiato e incollato in un editor SE come un'immagine è piuttosto fastidioso, quindi per favore non farlo. Invece, seleziona il testo nel tuo terminale e premi CTRL-MAIUSC-C.
cat

Risposte:


25

Questa è una funzionalità documentata.

Se si esegue bash tramite un collegamento simbolico denominato sh, bash verrà avviato in shmodalità compatibilità.

Da man bash:

Se bash viene invocato con il nome sh, cerca di imitare il comportamento di avvio delle versioni storiche di sh il più vicino possibile, pur rispettando lo standard POSIX. Quando viene invocato come shell di login interattivo o come shell non interattiva con l'opzione --login, tenta innanzitutto di leggere ed eseguire i comandi da / etc / profile e ~ / .profile, in questo ordine. L'opzione --noprofile può essere utilizzata per inibire questo comportamento. Quando viene invocato come shell interattiva con il nome sh, bash cerca la variabile ENV, espande il suo valore se è definito e utilizza il valore espanso come nome di un file per leggere ed eseguire. Poiché una shell invocata come sh non tenta di leggere ed eseguire comandi da altri file di avvio, l'opzione --rcfile non ha alcun effetto. Una shell non interattiva invocata con il nome sh non tenta di leggere altri file di avvio. Quando viene invocato come sh, bash entra in modalità posix dopo la lettura dei file di avvio.

Come fa un programma a sapere quale nome è stato usato per avviarlo?

Se è un programma CA, può ispezionare argv[0]. Se è uno script shell o perl, può controllare $0.

Ad esempio, consideriamo questo semplice script di shell:

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

$0è il nome da cui è stato chiamato lo script. ${0##*/}è il nome che è stato chiamato lo script con tutti i nomi di directory rimossi.

Creiamo questo link simbolico:

ln -s utc et

Quindi, utce etentrambi gestiscono lo stesso eseguibile ma forniscono risultati diversi. Quando eseguito come utc, emette tempo universale. Se eseguito come et, viene emesso il fuso orario degli Stati Uniti orientali. Per esempio:

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

4
Potrebbe voler aggiungere come ciò sia possibile, poiché l'OP si aspetta che le chiamate siano identiche. ( argv[0], obvs)
Razze di leggerezza in orbita,

@LightnessRacesinOrbit Buona idea. Ho aggiunto un esempio.
Giovanni 1024,

Perfetto adesso. :)
Razze di leggerezza in orbita
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.