GNU/Linux >> Linux Esercitazione >  >> Linux

Quando devo usare #!/bin/bash e quando #!/bin/sh?

In breve:

  • Esistono diverse shell che implementano un superset della specifica POSIX sh. Su sistemi diversi, /bin/sh potrebbe essere un collegamento ad ash, bash, dash, ksh, zsh, &c. (Sarà sempre compatibile con sh – mai csh o fish.)

  • Finché ti attieni a sh solo funzionalità, puoi (e probabilmente anche dovresti) usare #!/bin/sh e lo script dovrebbe funzionare bene, non importa quale shell sia.

  • Se inizi a utilizzare funzionalità specifiche di bash (ad esempio gli array), dovresti richiedere specificatamente bash, perché, anche se /bin/sh già invoca bash sul tuo sistema, potrebbe non essere su tutti gli altri system e il tuo script non verrà eseguito lì. (Lo stesso ovviamente vale per zsh e ksh.) Puoi usare shellcheck per identificare i bashismi.

  • Anche se lo script è solo per uso personale, potresti notare che alcuni sistemi operativi cambiano /bin/sh durante gli aggiornamenti, ad es. su Debian era bash, ma in seguito è stato sostituito con trattino molto minimale. Script che usavano bashismi ma avevano #!/bin/sh improvvisamente rotto.

Tuttavia:

  • Anche #!/bin/bash non è molto corretto. Su sistemi diversi, bash potrebbe risiedere in /usr/bin o /usr/pkg/bin o /usr/local/bin .

  • Un'opzione più affidabile è #!/usr/bin/env bash , che usa $PATH. (Sebbene il env nemmeno lo strumento stesso è strettamente garantito, /usr/bin/env funziona ancora su più sistemi rispetto a /bin/bash fa.)


Usa lo shebang corrispondente alla shell che hai effettivamente utilizzato per sviluppare ed eseguire il debug del tuo script. Cioè. se la tua shell di login è bash , ed esegui il tuo script come eseguibile nel tuo terminale, usa #!/bin/bash . Non dare per scontato che dal momento che non hai utilizzato gli array (o qualsiasi altra cosa bash caratteristica di cui sei a conoscenza), sei sicuro di scegliere qualunque shell ti piaccia. Ci sono molte sottili differenze tra le shell (echo , funzioni, cicli, ecc.) che non possono essere scoperti senza test adeguati.

Considera questo:se lasci #!/bin/bash e i tuoi utenti non ce l'hanno, vedranno un chiaro messaggio di errore, qualcosa come

Error: /bin/bash not found

La maggior parte degli utenti può risolvere questo problema in meno di un minuto installando il pacchetto appropriato. D'altra parte, se sostituisci shebang con #!/bin/sh e provalo su un sistema in cui /bin/sh è un collegamento simbolico a /bin/bash , i tuoi utenti che non hanno bash sarà nei guai. Molto probabilmente vedranno un messaggio di errore criptico come:

Error in script.sh line 123: error parsing token xyz

Questo potrebbe richiedere ore per essere risolto e non ci sarà alcun indizio su quale shell avrebbero dovuto usare.

Non ci sono molti motivi per cui vorresti usare una shell diversa nello shebang. Uno dei motivi è quando la shell che hai usato non è molto diffusa. Un altro è migliorare le prestazioni con sh che è significativamente più veloce su alcuni sistemi E il tuo script sarà un collo di bottiglia delle prestazioni. In tal caso, prova a fondo il tuo script con la shell di destinazione, quindi modifica lo shebang.


Dovresti usare solo #! /bin/sh .

Non dovresti mai usare estensioni bash (o zsh, o fish, o ...) in uno script di shell.

Dovresti scrivere solo script di shell che funzionano con qualsiasi implementazione del linguaggio della shell (compresi tutti i programmi di "utilità" che accompagnano la shell stessa). In questi giorni puoi probabilmente prendi POSIX.1-2001 (non -2008) come autorevole per ciò di cui sono capaci la shell e le utilità, ma tieni presente che un giorno potresti essere chiamato a portare il tuo script su un sistema legacy (ad esempio Solaris o AIX) la cui shell e utilità sono state bloccate intorno al 1992.

Cosa, sul serio?!

Sì, sul serio.

Ecco il punto:Shell è un terribile linguaggio di programmazione. L'unico vantaggio è che /bin/sh è l'unico interprete di script che ogni L'installazione Unix è garantita.

Ecco l'altra cosa:alcune iterazioni dell'interprete principale Perl 5 (/usr/bin/perl ) è più probabilmente disponibile su un'installazione Unix selezionata casualmente rispetto a (/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash è. Altri buoni linguaggi di scripting (Python, Ruby, node.js, ecc. - includerò anche PHP e Tcl in quella categoria quando li confronto con shell) sono disponibili più o meno quanto bash e altre shell estese.

Pertanto, se hai la possibilità di scrivere uno script bash, hai invece la possibilità di utilizzare un linguaggio di programmazione che non sia terribile.

Ora, semplice script di shell, del tipo che esegue solo alcuni programmi in sequenza da un cron job o qualcosa del genere, non c'è niente di sbagliato nel lasciarli come script di shell. Ma i semplici script di shell non hanno bisogno di array o funzioni o [[ anche. E dovresti scrivere solo complicato script di shell quando non hai altra scelta. Gli script di Autoconf, per esempio, sono propriamente ancora script di shell. Ma quegli script devono essere eseguiti su ogni incarnazione di /bin/sh che è rilevante per il programma che si sta configurando. e ciò significa che non possono utilizzare alcuna estensione. Probabilmente non devi preoccuparti dei vecchi Unix proprietari di questi tempi, ma probabilmente dovresti si preoccupano degli attuali BSD open-source, alcuni dei quali non installano bash per impostazione predefinita e ambienti incorporati che forniscono solo una shell minima e busybox .

In conclusione, il momento in cui ti ritrovi a volere una caratteristica che non è disponibile nel linguaggio della shell portatile, che è un segno che lo script è diventato troppo complicato per rimanere uno script di shell. Riscrivilo invece in un linguaggio migliore.


Linux
  1. In che modo Linux gestisce più separatori di percorsi consecutivi (/home////nomeutente///file)?

  2. È consentito lo spazio tra #! E /bin/bash a Shebang?

  3. Bash =~ Regex e HTTPS://regex101.com/?

  4. Qual è la differenza tra /sbin/nologin e /bin/false?

  5. Perché nessuno usa la vera shell Bourne come /bin/sh?

/usr/bin Vs /usr/local/bin Su Linux?

Cosa c'è di diverso tra /bin/false e /sbin/nologin come shell dell'utente nologin

Qual è la differenza tra #!/usr/bin/env bash e #!/usr/bin/bash?

Qual è il significato di /usr/sbin, /usr/local/sbin e /usr/local/bin?

Spostato il contenuto di /bin in /usr/bin, è possibile annullare?

#!/bin/sh vs #!/bin/bash per la massima portabilità