Qual è il Bash Shebang preferito?


1132

C'è qualche Bashshebang oggettivamente migliore degli altri per la maggior parte degli usi?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -
  • eccetera

Ricordo vagamente molto tempo fa di aver sentito che aggiungere un trattino alla fine impedisce a qualcuno di passare un comando al tuo copione, ma non riesco a trovare alcun dettaglio al riguardo.


4
Ed è /usr/local/bin/bashsu OpenBSD.
jww

Risposte:


1536

Dovresti usare #!/usr/bin/env bashper la portabilità : diversi * nix posizionati bashin luoghi diversi, e usare /usr/bin/envè una soluzione alternativa per eseguire il primo bashtrovato sul PATH. E shnon lo èbash .


9
Grazie. Sembra anche che aggiungere - alla fine di $! / Usr / bin / env bash - non farà nulla poiché un solo argomento è consentito da * nix nello shebang, e che viene usato da 'bash'. Ciò è apparentemente utile solo per impedire che argomenti dannosi vengano passati allo script dalla riga di comando se lo shebang dello script è uno degli altri senza argomenti ( /bin/sh, ecc.).
Kurtosis,

13
@Ray bashnon vive /binsu tutti i sistemi.
ptierno,

12
Lo stesso per me, l'ho appena aggiunto a un alias: alias shebang='echo "#!/usr/bin/env bash"'ora devo solo aprire il terminale e digitare shebang invece di andare qui.
Oylex

19
Questa risposta è ingannevole. POSIX non dice che envè a /usr/bin/env. Potrebbe essere /bin/envovunque o in realtà, purché sia ​​lungo il percorso. Potrebbe essere /dummy/envse /dummyè dentro PATH. Shebang stesso non è definito in POSIX, quindi ho potuto #!stop toasteravviare la macchina da caffè USB ed essere conforme a POSIX. Quindi #!/usr/bin/env bashnon è particolarmente meglio di #!/bin/bash, potrebbe essere meno portatile a seconda.
darkfeline

19
@darkfeline La portabilità non è assoluta - è matematicamente impossibile creare qualsiasi script che farà la stessa cosa su ogni piattaforma. A partire dal 2012 fino al 2018 /usr/bin/envesiste su un numero maggiore di macchine rispetto a uno dei due /bin/bashxor /usr/bin/bash, quindi uno script che inizia con questa riga farà la cosa prevista su quante più macchine possibile.
l0b0

80

/bin/shdi solito è un collegamento alla shell predefinita del sistema, che è spesso bashma attiva, ad esempio, i sistemi Debian hanno il peso più leggero dash. In entrambi i casi, la shell Bourne originale è sh, quindi se il tuo script utilizza alcune caratteristiche specifiche bash(2a generazione, "Bourne Again sh") ( [[ ]]test, array, varie cose zuccherine, ecc.), Allora dovresti essere più specifico e usare la versione successiva . In questo modo, sui sistemi in cui bash non è installato, lo script non verrà eseguito. Capisco che potrebbe esserci un'eccitante trilogia di film su questa evoluzione ... ma potrebbe essere sentito.

Si noti inoltre che quando viene evocato come sh, bashin una certa misura si comporta come standard POSIX sh (vedere anche i documenti GNU su questo).


2
Public Domain Korn Shell (pdksh) è di default su OpenBSD.
jww

La maggior parte dei sistemi non si collegherà /bin/shda nessuna parte /usrperché ciò renderebbe piuttosto difficile l'esecuzione degli script init prima del /usrmontaggio.
aij

@aij Non so perché ho messo "molti o più" lì - Sono un utente fedora, dove /bine /sbinper anni sono stati solo collegamenti simbolici per impostazione predefinita, a /usr/bine /usr/sbin, quindi in quel contesto /bin/shè un collegamento bashae l'attuale directory è /usr/bin. Ma correggerò quanto sopra.
delicateLatticework

44

Consiglio di usare:

#!/bin/bash

Non è portatile al 100% (alcuni sistemi si trovano bashin una posizione diversa da /bin), ma il fatto che molti script esistenti utilizzino #!/bin/bashpressioni di vari sistemi operativi per creare /bin/bashalmeno un collegamento simbolico alla posizione principale.

L'alternativa di:

#!/usr/bin/env bash

è stato suggerito, ma non vi è alcuna garanzia che il envcomando sia /usr/bin(e ho usato sistemi dove non lo è). Inoltre, questo modulo utilizzerà la prima istanza di bashnegli utenti attuali $PATH, che potrebbe non essere una versione adatta della shell bash.

(Ma /usr/bin/envdovrebbe funzionare su qualsiasi sistema ragionevolmente moderno, sia perché envè /usr/bino perché il sistema fa qualcosa per farlo funzionare. Il sistema a cui ho fatto riferimento sopra era SunOS 4, che probabilmente non ho usato in circa 25 anni.)

Se è necessario eseguire uno script su un sistema che non ha /bin/bash, è possibile modificare lo script in modo che punti nella posizione corretta (è certamente scomodo).

Ho discusso i compromessi in modo più approfondito nella mia risposta a questa domanda .

Un aggiornamento un po 'oscuro: un sistema che uso, Termux , un livello desktop-simile a Linux che funziona con Android, non ha /bin/bash( bashè /data/data/com.termux/files/usr/bin/bash) - ma ha una gestione speciale da supportare #!/bin/bash.


3
2 anni dopo e questo è ancora il miglior consiglio qui. Se la soluzione semplice non funziona, devi mettere in discussione le tue decisioni precedenti. La risposta accettata e più votata non è sbagliata, non è giusto :)
Software Engineer

27

Usare una linea shebang per invocare l'interprete appropriato non è solo per BASH. Puoi usare shebang per qualsiasi linguaggio interpretato sul tuo sistema come Perl, Python, PHP (CLI) e molti altri. A proposito, lo shebang

#!/bin/sh -

(può anche essere due trattini, cioè --) termina le opzioni bash tutto ciò che verrà trattato come nomi di file e argomenti.

L'uso del envcomando rende lo script portatile e consente di impostare ambienti personalizzati per lo script, pertanto gli script portatili devono essere utilizzati

#!/usr/bin/env bash

O qualunque sia la lingua come per Perl

#!/usr/bin/env perl

Assicurati di guardare le manpagine per bash:

man bash

e env:

man env

Nota: Sui sistemi basati su Debian e Debian, come Ubuntu, shè collegato a dashno bash. Come usano tutti gli script di sistema sh. Ciò consente a bash di crescere e al sistema di rimanere stabile, secondo Debian.

Inoltre, per mantenere invocazione * nix come se non avessi mai usato estensioni di file su script invocati shebang, poiché non è possibile omettere l'estensione su invocazione su file eseguibili come è possibile su Windows. Il comando file può identificarlo come uno script.


4

Dipende molto da come scrivi i tuoi script bash. Se hai un /bin/shlink simbolico a bash, quando bash viene invocato come sh, alcune funzionalità non sono disponibili .

Se si desidera funzionalità specifiche di bash, non POSIX, utilizzare #!/bin/bash


3
Bash non è installato su OpenBSD. Se lo installi tramite pkg_add, allora si trova in /usr/local/bin, che potrebbe non essere sul percorso.
jww

che ne dici di una POSIXfunzione?
Nikolan Asad,
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.