Qual è la differenza tra l'esecuzione di "bash script.sh" e "./script.sh"?


42

Se script.sh è solo qualcosa di tipico

#!/bin/bash
echo "Hello World!"

Esiste un modo preferito per eseguire lo script? Penso che devi prima modificarlo in modo che diventi eseguibile?

Risposte:


56

Per il tuo script specifico funzionerà in entrambi i modi, tranne per il fatto che ./script.shrichiede l'esecuzione e bit leggibili, mentre bash script.shrichiede solo bit leggibili.


Il motivo della differenza dei requisiti di autorizzazione risiede nel modo in cui viene caricato il programma che interpreta lo script:

  • ./script.sh fa eseguire alla shell il file come se fosse un normale eseguibile.

La shell execveesegue il fork stesso e utilizza una chiamata di sistema (ad es. ) Per fare in modo che il sistema operativo esegua il file nel processo a fork. Il sistema operativo controllerà le autorizzazioni del file (quindi è necessario impostare il bit di esecuzione) e inoltrerà la richiesta al programma di caricamento del programma , che controlla il file e determina come eseguirlo. In Linux gli eseguibili compilati iniziano con un numero magico ELF , mentre gli script iniziano con un #!( hashbang ). Un'intestazione hashbang significa che il file è uno script e deve essere interpretato dal programma specificato dopo l'hashbang. Ciò consente a uno script stesso di indicare al sistema come interpretare lo script.

Con lo script, il programma di caricamento programma verrà eseguito /bin/bashe passato ./script.sh come argomento della riga di comando.

  • bash script.shfa funzionare bashe passare la shell script.shcome argomento della riga di comando

Quindi il sistema operativo verrà caricato bash(nemmeno guardando script.sh, perché è solo un argomento della riga di comando). Il bashprocesso creato interpreterà quindi script.shperché è passato come argomento della riga di comando. Poiché script.shviene letto solo bashcome file normale, il bit di esecuzione non è richiesto.


Ti consiglio di usare ./script.shperò, perché potresti non sapere quale interprete richiede lo script. Quindi lascia che il programma di caricamento programmi lo determini per te.


3
Se il bit eseguibile non è impostato, è anche possibile eseguire lo script facendo ". ./Script.sh"
Cane mangia gatto mondo

1
@ Dog Hai ragione. Il punto è una scorciatoia per il comando incorporato 'source', che esegue lo script nel processo bash corrente. Quindi è richiesto solo il bit leggibile.
SkyDan,

5
@Dogeatcatworld mentre questo è vero, l'esecuzione . ./script.shnon è la stessa cosa bash script.sh(o ./script.shConsiderare lo script. #!/usr/bin/python -V<Newline> print test.
Casey

12
Attenzione che l'approvvigionamento di uno script potrebbe provocare la contaminazione della sessione interattiva. Ad esempio, se uno script modifica la variabile di ambiente PATH, questa modifica influirà sui comandi eseguiti seguendo l'origine. Questo approccio dovrebbe davvero essere riservato per le situazioni in cui si dipende dagli effetti collaterali (script di installazione dell'ambiente e simili). Per altre situazioni in cui non è possibile modificare le autorizzazioni, l'esecuzione del comando nella riga shebang, seguita dal nome dello script è l'approccio più sicuro.
ctt

6
Si noti che, se si genera uno script nella directory corrente, non è necessario utilizzare ./ ; basta dire . script.sh. Ma sono d'accordo con le persone che scoraggiano l'uso del .comando su script che non avrebbero dovuto essere invocato in quel modo. Sono sorpreso che nessuno abbia menzionato il fatto che, se lo script contiene exitcomandi e tu lo procuri, potrebbe disconnetterti. Un problema meno terribile sarebbe se lo script fa un cd, poiché ciò influenzerebbe anche la shell genitore (interattiva).
Scott,

18

bash script.shinvoca direttamente lo script usando bash.
./script.shsta usando lo shebang #!/bin/bashper determinare come eseguire.

Se vuoi davvero sapere, quale binario viene eseguito se lo fai, bash script.shpotresti scoprirlo which bash.

Quindi nel tuo esempio non fa differenza. Sì, devi chmod +x script.shessere in grado di eseguirlo direttamente tramite ./script.sh.


2
Bene, non fa differenza supponendo che /bin/bashsia il primo bashnel tuo $PATH.
cjm

Hai ragione. E lo shebang #!/bin/bashfunziona solo se c'è un/bin/bash
xx4h

Bash (versione 4.2.37) sul mio sistema esegue script anche senza il bit di esecuzione impostato. Perché dici che è richiesto il bit di esecuzione?
SkyDan,

Sì, il bit di esecuzione è necessario solo invocando via ./script.sh.
xx4h,

4

Crea un file Delete_Self.sh in questo modo:

 #!/bin/rm

 echo I am still here!

Esegui questo script come sh Delete_Self.shvedrai "Sono ancora qui!" riecheggiò.

Renderlo eseguibile ed eseguirlo come ./Delete_Self.shnon vedrai nulla di echo indietro, mentre il file Delete_Self.shstesso è sparito.

Quindi la differenza è che:

  • bash script.shignorerà il #! linea, perché bash è specificato come programma per eseguire script.sh.
  • ./script.shleggerà il #! linea per determinare il programma da eseguire script.sh.

+1 per il bell'esempio
ThisaruG

1

Oltre alle altre risposte, è utile conoscere la differenza tra l'esecuzione di uno script tramite ./script.sh(i) e source ./script.sh(ii) - La versione (i) crea una nuova shell in cui eseguire il comando, mentre (ii) lo esegue nel shell corrente - che può essere obbligatoria se l'eseguibile cambia le variabili di ambiente che devono essere conservate dopo la chiusura dell'eseguibile. Ad esempio, per attivare un ambiente conda python è necessario utilizzare quanto segue:

source activate my_env

NB Un'altra alternativa a sourcequella che potresti incontrare è quella .incorporata, ovvero

. activate my_env
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.