Esecuzione di uno script di shell quando “/ bin / sh” punta a “/ bin / bash”


11

Ho letto quanto segue in questa domanda :

bash supporta uno switch --posix, che lo rende più conforme a POSIX. Prova anche a imitare POSIX se invocato come sh .

La citazione sopra presuppone che /bin/shsia un collegamento a cui punta /bin/bash.

Ma non capisco bene cosa si intende per "invocato come sh" .


Dì che ho il seguente script che si chiama "script.sh":

#!/bin/bash
echo "Hello World"

Per favore, dimmi in ciascuno dei seguenti casi se lo script verrà eseguito in bashmodalità normale o POSIX (supponi che io abbia eseguito i seguenti comandi in un terminale che è in esecuzione bash):

  1. sh script.sh
  2. bash script.sh
  3. ./script.sh

Ora dì che ho il seguente script che si chiama "script.sh" (che è come lo script sopra ma senza lo shebang):

echo "Hello World"

Per favore, dimmi in ciascuno dei seguenti casi se lo script verrà eseguito in bashmodalità normale o POSIX (supponi che io abbia eseguito i seguenti comandi in un terminale che è in esecuzione bash):

  1. sh script2.sh
  2. bash script2.sh
  3. ./script2.sh

Risposte:


19

Solo i casi 1 e 4 verranno eseguiti in modalità POSIX (supponendo che shsia bash e non qualche altra implementazione di sh). Qualsiasi caso che chiami esplicitamente bashsenza lo --posixfarà, che sia dallo shebang o no. Ogni caso che chiama esplicitamente lo shfarà. Lo shebang è usato solo quando nessuna shell è stata già esplicitamente avviata per lo script.

Il caso 6, se il terminale è in esecuzione bash, non funzionerà in modalità POSIX e Bash lo invocherà usando se stesso. Se invece il tuo terminale eseguisse zsh, il caso 6 verrebbe eseguito anche in modalità POSIX. POSIX è ambiguo riguardo esattamente cosa dovrebbe succedere in quel caso , e Bash e zsh hanno fatto diverse scelte lì. Bash invoca lo script usando se stesso, mentre zsh usa sh(qualunque cosa accada). Anche altre shell variano su quel punto.


Un modo semplice per dire in che modalità sei è creare il tuo corpo di script:

kill -SIGHUP

che fallirà con un errore in modalità POSIX , ma fornirà istruzioni per l'uso killal di fuori di esso. Questa è una distinzione facile e funziona attraverso una vasta gamma di versioni di Bash che risale al più presto possibile.


3
Ci sono altre cose che forzeranno bashl'esecuzione in modalità POSIX come la POSIXLY_CORRECTvariabile d'ambiente o SHELLOPTS=posix.
Stéphane Chazelas,

1
[ -o posix ]è un modo più ovvio per verificare che tu stia eseguendo in modalità posix in bash (non in altre shell (tranne yash), quindi non vorrai farlo in uno shscript). POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'uscite yes`
Stéphane Chazelas,

2
Nel caso 6, bash invoca lo script con se stesso in modalità POSIX quando è esso stesso in modalità POSIX come richiede POSIX. POSIX non specifica il meccanismo she-bang, e 6 è l'unico modo POSIX per avere script eseguibili ed è chiaramente specificato (in ambienti POSIX, lo script deve essere interpretato da un'utilità sh conforme).
Stéphane Chazelas,

8

Il "invocato come" si riferisce a qualunque è che il processo partendo mette Bash nel suo argomento riga di comando "zeroth" argv[0].

Quando un programma viene avviato con i exec*()syscalls , non conoscono realmente il nome del file binario contenente il programma, ma invece il processo di chiamata è libero di inserire quello che vuole lì. Di solito, ovviamente, il nome viene preso dal filesystem, quindi se lo esegui /bin/sh, è quello che viene messo lì. E se /bin/shè Bash, non deve essere un collegamento simbolico, potrebbe essere un collegamento reale o solo un'altra copia del programma shell.

Come esempio di impostazione del "nome del programma", il execcomando di Bash può impostare l'argomento zeroth con l' -aopzione. (Potremmo fare lo stesso con Perl o direttamente con C, ecc.)

Ecco mynameun semplice programma C che stampa solo il suo argomento zeroth, il nome che vede se stesso:

$ ./myname 
I am ./myname
$ (exec -a something ./myname )
I am something
$ mv ./myname somename
$ ln -s somename othername
$ ./somename 
I am ./somename
$ ./othername
I am ./othername

Fonte:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("I am %s\n", argv[0]);
    return 0;
}

Ma, per rispondere alle domande numerate ...

(1 & 4) running sh somescriptfunzionerà qualunque cosa shsia sulla tua PATH, probabilmente /bin/shma forse qualcosa del genere/usr/xpg4/bin/sh .

  • Se è Bash, viene eseguito in modalità POSIX, poiché vede il nome sh.
  • Se è la shell Z o la shell Korn, allo stesso modo vede il nome sh, ma funziona in modalità "SH compatibile", che mira a essere compatibile con la shell Bourne ed è leggermente diverso dalla modalità conforme POSIX completa in entrambe le shell .
  • Potrebbe essere la conchiglia Almquist, una vera conchiglia Bourne, o qualcos'altro, ovviamente.

(2 & 5) Esecuzione bash somescriptverrà eseguito in modalità Bash regolare (di nuovo, ovviamente dipende da cosa bashnei vostri PATHIS.)

(3) Qui, il nome dello script viene dato direttamente alla chiamata di sistema al posto del file di programma. Il kernel legge la riga hashbang e la usa per eseguire lo script.

(6) Questo è quello complesso. È simile a (3), ma la chiamata di sistema per l'avvio del programma fallisce ( ENOEXEC (Exec format error)), poiché non esiste una linea hashbang. Quello che succede dopo dipende dal fatto che la shell in esecuzione sia essa stessa in modalità POSIX. POSIX richiede che una shell conforme a POSIX si comporti in un modo specifico in risposta a ENOEXEC. Tuttavia, esiste un margine di manovra in "un comando equivalente a quello di invocare una shell", il che significa che shell diverse fanno cose diverse.

  • La shell Bourne Again si esegue nuovamente nella stessa modalità con il nome dello script come primo argomento della riga di comando. Nella sua modalità conforme a POSIX, sta ovviamente eseguendo se stesso nella sua modalità conforme a POSIX, obbedendo così al requisito POSIX di invocare una shell conforme a POSIX.
  • La shell Z, la shell Almquist e la shell Korn vengono eseguite /bin/shcon il nome dello script inserito prima degli altri argomenti come primo argomento della riga di comando. La shell Z, la shell Almquist e la shell Korn stanno (tentando) di invocare una shell conforme a POSIX a forza di supporre che il /bin/shprogramma sia uno.

Potresti condividere il codice sorgente di questo programma C. ..
GypsyCosmonaut

int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Stig Hemmer,

È praticamente tutto.
Ilkkachu,

4

Il guscio è eseguita sia quella chiamata nella riga di comando o l'uno nel shebang (se la riga di comando non specifica esso).

Pertanto, le versioni 1 e 4 verranno eseguite con sh, 2 e 5 con bash e 6 potrebbero non funzionare se si utilizza sh (e alcuni altri) in modo interattivo. Bash avvia lo script. Ksh anche. Zsh lo avvia come sh.

Solo quelli avviati come shuseranno l'opzione posix se bash è collegato /bin/sh.

Aggiungi questa riga al tuo script per rilevare se è in esecuzione una versione bash ksh o zsh:

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
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.