C'è qualche motivo per avere un shebang che punta su / bin / sh anziché / bin / bash?


53

Nella maggior parte degli script di shell che ho visto (oltre a quelli che non ho scritto da solo), ho notato che Shebang è impostato su #!/bin/sh. Questo non mi sorprende molto con gli script più vecchi, ma è presente anche con script abbastanza nuovi.

C'è qualche motivo per preferire /bin/shsopra /bin/bash, dal momento che bashè praticamente onnipresente, e spesso di default, su molte macchine Linux e BSD che risale oltre un decennio?


23
È una buona partice da usare /bin/shse non si utilizzano bashfunzioni specifiche . Un giorno potresti dover usare uno dei tuoi script su un sistema su cui non è installato (server remoto, computer incorporato ...)
Mathieu

1
in generale dovresti evitare di porre domande che si prestano a risposte basate sull'opinione (che è l'unico modo possibile in cui credo che si possa rispondere a questa domanda - ma questa è solo la mia opinione ) .
Mikeserv,

9
Credo che sia possibile rispondere a questa domanda senza coinvolgere la mera opinione, indicando almeno due organizzazioni che hanno affrontato questa cosa per diversi anni e guardando la storia e il risultato. Con molte altre letture allegate, per l'avvio. ☺
JdeBP il

3
@JulesMazur Un'affermazione ...the answers so far are fairly subjective..."soggettiva" è essenzialmente basata sull'opinione per definizione. /bin/bashdovrebbe essere usato solo quando bash è esplicitamente necessario. In oltre 40 anni come sviluppatore, molto prima bash, non ne avevo quasi mai esplicitamente bisogno, tranne durante i test. (Mi sforzo anche di evitare le estensioni della shell, ma la maggior parte dei miei script sono destinati alla distribuzione.) Molti script in rete dovrebbero anche essere destinati ad un ampio utilizzo.
user2338816

2
@ user2338816 mio male, intendevo obiettivo . Grazie per i tuoi punti!
Jules il

Risposte:


83
  1. Ci sono sistemi che non spediscono bash di default (es. FreeBSD).
  2. Anche se bash è installato, potrebbe non trovarsi in /bin.
  3. Gli script più semplici non richiedono bash.
  4. L'uso della shell POSIX è più portatile e gli script verranno eseguiti su una maggiore varietà di sistemi.

17
Un altro motivo: spesso / bin / sh è più veloce di bash, o almeno si carica più velocemente (perché è più piccolo).
derobert il

5
@derobert, /bin/shè più veloce se non lo è bash, ci sono ancora alcuni sistemi come OS / X o RHEL dove si /bin/shtrova bash.
Stéphane Chazelas,

1
No. Alcuni sistemi operativi lo collegano, perché bash è retrocompatibile.
Sobrique,

7
Alcuni script suppongono che lo /bin/shsia /bin/bash. Il passaggio da Ubuntu da bash a dash li ha interrotti tutti.
atamanroman,

19
@atamanroman: gli script erano in primo luogo errati, avrebbero dovuto usarli #!/bin/bashse volevano Bash (niente di sbagliato in questo!). Il cambiamento è stato principalmente eseguito a monte in Debian. Ha migliorato l'esperienza dell'utente, ha avuto un impatto misurabile sul tempo di avvio del sistema. Ha inoltre influito positivamente sulla sicurezza, vedere "Shellshock".
Dietrich Epp,

28

La maggior parte degli script di sistema in (correlati a Debian: Ubuntu, Mint, ecc.) Linux sono scritti per essere eseguiti nel trattino più veloce, che è l'impostazione predefinita / bin / sh in quei sistemi. Il motivo è duplice:

  • Velocità del sistema. Un codice di trattino più piccolo si carica più velocemente e funziona anche più velocemente. Con qualche (piccolo?) Ulteriore sforzo (costo) per i programmatori di script di shell.

  • Sicurezza. La diversità delle conchiglie aiuta a resistere ai bug. I sistemi Debian non erano per lo più vulnerabili allo shellshock perché la shell predefinita non aveva tale vulnerabilità.

Bash è in effetti la shell predefinita per gli utenti , poiché è più potente e ha molti più elementi per facilitare la codifica. È anche l'impostazione predefinita shin Mac OS (quella collegata da / bin / sh). Tuttavia, chiamare bashcon il nome del collegamento di shfa in modo che inizi come una shell conforme a posix.


2
Un set più limitato di strumenti disponibili di una shell più semplice rende la scrittura del codice più difficile (si prega di evitare qualsiasi guerra fanatica su questo). Ecco perché ad alcuni utenti piace zsh, che ha ancora più strumenti disponibili di bash. Mi piace di più Bash e l'equilibrio tra i due estremi.

4
@RobertL, molte delle funzionalità aggiunte in ksh e adottate da bash esistono perché facilitano sostanzialmente il processo di scrittura di script robusti e corretti. Senza le varie aggiunte che consentono l'assegnazione e la valutazione indirette da eseguire in modo sicuro, ad esempio, ci si può trovare ad utilizzare eval, con conseguente esposizione di sicurezza; allo stesso modo, senza il supporto regex integrato, è possibile utilizzare i comandi esterni (con un forte dispendio di prestazioni) per la corrispondenza anche all'interno di una sola riga, ecc.
Charles Duffy,

1
@RuiFRibeiro, nulla è staticamente collegato in Debian. Dash è più limitato, ma è limitato principalmente nelle funzionalità interattive (nessun completamento e simili), quindi è più veloce per gli script.
Jan Hudec,

21

Altri hanno sottolineato che le premesse della domanda, che la shell Bourne Again è predefinita e onnipresente, sono decisamente sbagliate.

Inoltre, ci sono davvero buone ragioni per usare qualcosa di diverso dalla shell Bourne Again per interpretare gli script della shell. Queste ragioni hanno motivato il grande progetto di Ubuntu e Debian, nel corso di diversi anni, per rimuovere i bashismi e far sì che molti degli script di shell fossero eseguiti dall'inizializzazione del sistema (che era un sacco di script di shell con System 5 rc) e l'installazione / rimozione dei pacchetti usa il Shell Debian Almquist invece della shell Bourne Again.

In poche parole: la shell Bourne Again, piena zeppa di funzionalità interattive com'è, non è l'interprete shell più veloce per uno script di shell conforme a POSIX. Quindi se uno può rendere i propri script shell conformi a POSIX, interpretandoli con un programma più leggero, come la shell Debian Almquist, il proprio sistema funzionerà meglio. (Alla fine, Debian ha dovuto apportare lievi modifiche alla shell Almquist, per aggiungere il supporto per un paio di costrutti shell non POSIX che erano semplicemente troppo profondamente e ampiamente incorporati e troppo utili per sbarazzarsi di.)

Il risultato è stato un grande vantaggio nelle prestazioni del bootstrap.

Quindi ci sono due distinte classi di shell da considerare, qui:

  • Le shell con tutte le funzionalità interattive appariscenti, che sono configurate come shell di accesso interattive per gli utenti nel database degli account.
  • Le shell che interpretano rapidamente molti script, che vengono utilizzate come interpreti di script dai programmi di script di shell.

Si noti che parlare di questo come "preferire /bin/sh" è semplificare eccessivamente. Debian in realtà aveva almeno due obiettivi:

  1. Di fronte agli amministratori che usano la shell Debian Almquist, la shell Z (in modalità POSIX), la shell Bourne Again (in modalità POSIX), la shell MirBSD Korn e altri come /bin/sh, c'erano ...

    1. ... rendendo gli script il più portatili possibile, in modo che il passaggio a ciò che è stato /bin/shmappato non abbia rotto le cose; o

    2. ... creare script non portatili indirizzare esplicitamente il programma interprete corretto , invece di aspettarsi semplicemente quella /bin/shmappa.

  2. C'era rendendo il Debian Almquist guscio la mappatura predefinita per /bin/shal posto del Bourne Shell, in modo che tali script che erano POSIX-conforme (o, più propriamente, Debian Policy Manual conforme) correva più rapidamente.

E ovviamente una volta che ci si immerge in questo, si può andare molto oltre; come considerare i compromessi di efficienza di simili /bin/trueed /usr/bin/clearessere script di shell o programmi compilati. Ma questo va oltre lo scopo di questa risposta, per fortuna. ☺

Niente di tutto questo è molto nuovo, nemmeno specifico per Unix, ovviamente. Già prima della fine del secolo, ho scritto e pubblicato un interprete da riga di comando che presentava sapori sia "interattivi" che "non interattivi", spiegando questa stessa divisione nel suo doco e notando la differenza tra le variabili COMSPECe OS2_SHELLambiente. Allo stesso modo, la discussione sulla rimozione dei bashismi nel sistema V di Debian rce negli script di installazione / rimozione dei pacchetti risale agli anni '90.

Ulteriori letture


2
"Alla fine, Debian ha dovuto apportare lievi modifiche alla shell Almquist, per aggiungere il supporto per un paio di costrutti shell non POSIX che erano semplicemente troppo profondamente e ampiamente incorporati e troppo utili per sbarazzarsi di." - Quale dei tuoi numerosi link contiene informazioni al riguardo? Sembra molto interessante. :)
Wildcard il

3
IMHO, le prestazioni sono solo una motivazione per convincere le persone a concordare con i cambiamenti. La prima grande ragione del cambiamento era che Bash continuava a rompere la compatibilità all'indietro. Personalmente ho dovuto risolvere i problemi di bash almeno 3 volte nella mia carriera perché lo script funzionava in una versione di bash ma falliva in un'altra (di solito succede dopo l'aggiornamento del sistema operativo). Dash non è semplicemente un interprete leggermente più veloce. È anche molto più stabile in termini di comportamento.
Slebetman,

Sarei interessato se i commenti nella Schily Bourne Shellpagina man, vedi schilytools.sourceforge.net/bosh.html, sono adatti a permettere alle persone di capire come scrivere una sceneggiatura portatile (dipende solo Bourne Shell featuresdal 1989). Quello che ho fatto è stato menzionare ogni miglioramento che non era nei vecchi Bourne Shells. BTW: Sono anche interessato a conoscere un elenco di bashismi in dash.
schily,

8

C'è qualche motivo per avere un shebang che punta su / bin / sh anziché / bin / bash?

Sì. L'ottima risposta di Marco Marco lo delinea bene.

Cosa dovrei usare nel mio shebang?

Quando scrivi i tuoi script, dovresti indicare lo shebang alla cosa più generale che hai testato.

Sul mio sistema (Centos 6.6), shè collegato a bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Ciò significa che uso sempre il #!/bin/bashmio shebang a meno che non abbia verificato che non ho dei bashims nella mia sceneggiatura.

Impostando shebang su di #!/bin/shte prometti che la sceneggiatura funzionerà con tutte le implementazioni di sh.

Questa è una promessa molto più grande del dire che la sceneggiatura funzionerà con bash.

Ecco un esempio di uno script che si comporterà in modo errato a seconda shdell'implementazione utilizzata dal sistema:

#!/bin/sh
n=1
a=$((++n))
echo $n

Quando si utilizza bashlo script verrà stampato:

2

Quando si utilizza dashlo script verrà stampato:

1

Se voglio usare #!/bin/shcosa devo fare?

  • Controlla lo script con checkbashisms- Nota che questo non troverà tutti i bashims. Non ha trovato il bashismo nella mia sceneggiatura sopra
  • Testa lo script usando un'altra shimplementazione. In genere collaudo con dash, tuttavia mi aspetto che alcuni bashismi o trattini possano ancora passare.

La pagina DashAsBinSh sulla wiki di Ubuntu contiene molte informazioni interessanti.


6
"Quando scrivi i tuoi script, dovresti indicare lo shebang alla cosa più generale contro cui hai testato .... Impostando lo shebang su #! / Bin / sh stai promettendo che lo script funzionerà con tutte le implementazioni di sh ". Punto eccellente . +1 e mi hai fatto ripensare a come scriverò le mie trans per il futuro. Grazie! :)
Wildcard il

2
Bene, non tutte le implementazioni di /bin/sh; solo quelli conformi a POSIX.
Blacklight Shining il

4

L'unico motivo rimanente per scrivere uno script di shell, anziché uno script in un linguaggio più potente ed ergonomico, è se la portabilità a sistemi legacy con un set sconosciuto di software installato è più importante di qualsiasi altro fattore .

/bin/shè l'unico e unico interprete di script disponibile su tutto ciò che si definisce Unix. Ma su moltissimi sistemi legacy /bin/she le utilità associate non sono nemmeno conformi alle specifiche POSIX.1-1996 "shell and utilities", per non parlare di qualcosa di più moderno. Gli strumenti conformi agli standard sono un componente aggiuntivo facoltativo, installato in /usr/xpg4una posizione non ovvia. 1 Lo scripting nel linguaggio della shell del sottoinsieme portatile è ancora più noioso e soggetto a errori rispetto allo scripting nel linguaggio della shell POSIX. (Leggi uno configurescript generato da Autoconf qualche volta se non mi credi. Solo l'installazione dovrebbe essere sufficiente per convincerti.)

Ma se si può presumere che sia installato qualsiasi altro interprete di script (ad esempio Bash), è possibile presupporre che sia installato un interprete per un linguaggio di scripting migliore . Perl, ad esempio, è più probabile che sia disponibile rispetto a Bash.

Pertanto, non dovresti mai scrivere uno #! /bin/bashscript, perché se questa è un'opzione, anche una lingua migliore è un'opzione.

1 Ad esempio, Solaris 10 e precedenti hanno spedito la shell Bourne originale come /bin/sh. Sono informato che Solaris 11 lo ha aggiornato a ksh93.


3
In quale lingua scriverai uno script per avviare un sistema? O all'interno di un router SOHO (sistemi a embebed limitati)? O su Android? Una shell sarà disponibile in tutti questi casi. Perl no.

1
Vi sono alcune imprecisioni sulle parti relative alla risposta di Solaris. Su Solaris 10 e versioni precedenti, non/bin/sh è POSIX.1-1996 ma in realtà una shell Bourne originale di sintassi pre-POSIX. Ciò rende un pessimo shebang per l'esecuzione degli script con queste versioni. Gli script portatili su Solaris utilizzerebbero che non saranno molto portabili su altri sistemi operativi. Sull'ultimo Solaris, Oracle Solaris 11 rilasciato per la prima volta nel 2011, è un moderno conforme alle recenti specifiche POSIX e con molte estensioni moderne. #!/bin/sh#!/usr/xpg4/bin/sh/bin/shksh93
jlliagre,

1
@BinaryZebra: "A shell" sarà disponibile, sì. Ma bash non è necessariamente quella shell (in particolare la maggior parte dei router SOHO ashche viene fornita con busybox), e tendo a pensare che zwol abbia ragione nel dire che perl è più comunemente disponibile di bash.
Ben Voigt,

1
@BenVoigt Sto commentando questa frase "L'unico motivo rimanente per scrivere uno script di shell". Ci sono ancora alcune istanze che richiedono una shell per alcune attività (non tutte). Erano alcuni casi dalla cima della mia testa. OTOH Nei sistemi con memoria sufficiente (quasi tutti negli standard odierni) e potenza sufficiente installare Perl (o Python, o ....) è abbastanza semplice e veloce. Tuttavia, non sto sostenendo alcuna shell specifica. Dove lo leggi nel mio commento?

2
Non sono assolutamente d'accordo con la tua affermazione altamente supponente e non fattuale secondo cui "se bashè disponibile, allora è una lingua migliore, quindi non dovresti mai scrivere alcun bashcodice". Inoltre, come sottolinea @sixtyfootersdude, dovresti sempre usarlo a #!/bin/bashmeno che tu non abbia verificato che lo script funzioni con qualsiasi shell POSIX.
Wildcard il

0

Dovresti effettivamente usare entrambi

#! /bin/env sh

o

#! /bin/env bash

in questo modo invochi una delle shell in base al modo in cui sono installate su quel sistema.

Per essere super sicuri ( ad esempio in caso di riavvii di singoli utenti), utilizzare shaltrimenti bash.


6
Da questa risposta : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.questo probabilmente vale anche per she bash.
Jules il

12
No, non dovresti usare #!/bin/envnulla in uno script portatile. È perfettamente ragionevole supporre che /bin/shesista ed è una shell funzionante, conforme a POSIX. D'altra parte, nessuno dei miei sistemi ha a /bin/env.
Blacklight Shining il

Anche un buon punto.
Jules il

1
@Blacklight Splendente è sicuramente sbagliato assumere una shell conforme a POSIX /bin/sh. POSIX non lo richiede e definisce piuttosto altre regole per ottenere un ambiente conforme POSIX su una piattaforma certificata POSIX.
schily,

4
/usr/bin/envnon è universalmente disponibile ...
vonbrand il
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.