Usa #! / Bin / sh o #! / Bin / bash per compatibilità Ubuntu-OSX e facilità d'uso e POSIX


18

So che posso usare entrambi come prima riga di script per invocare la shell desiderata.

Sarebbe #!/bin/shraccomandato se la compatibilità con tutti i sistemi unix è un requisito assoluto?

Nel mio caso, l'unico sistema operativo a cui tengo sono Ubuntu (Debian) e OSX. Detto questo, potrei usare #!/bin/bashed essere certo che funzionerebbe su entrambi i sistemi?
Ciò renderebbe anche più semplice l'uso di script con una sintassi più moderna e più chiara per i comandi? L'utilizzo #!/bin/shriguarda anche l'uso di POSIX?


1
Probabilmente vale la pena notare che molte distro hanno iniziato a fondersi /bine /usr/bin. Di conseguenza, è probabilmente meglio utilizzare #!/usr/bin/env <shname>per la portabilità in questi giorni.
HalosGhost

Risposte:


15

Per i principianti, se puoi supporre che Bash sia preinstallato (il che, per quanto ne so, è il caso su tutti i sistemi che elenchi), usa il seguente hashbang per essere compatibile:

#!/usr/bin/env bash

questo invoca qualunque bashcosa sia configurata, indipendentemente dal fatto che sia dentro /bino /usr/local/bin.

Mentre sulla maggior parte dei sistemi in una vasta gamma (inclusi AIX, Solaris, diversi tipi di BSD), sono bashfiniti in posizioni diverse, envfinendo sempre in /usr/bin/env. Il trucco, tuttavia, non è mio ma dell'autore del Bash Cookbook.

Comunque, sì, Bash ti permetterebbe di utilizzare alcune funzionalità "moderne" che ti semplificano la vita.

Ad esempio le doppie parentesi:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

mentre nei dialetti shell tradizionali dovresti ricorrere a:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

ma la cosa migliore delle doppie parentesi è che consentono espressioni regolari per la corrispondenza. Il Wiki di Bash Hackers ti darà molti trucchi in quella direzione.

Puoi anche usare espressioni abbastanza comode come $((2**10))o altre espressioni aritmetiche in linea con la $((expression))sintassi.

L'uso dei backtick per i subshells va bene, anche se un po 'obsoleto. Ma le capacità di nidificazione delle $(command ...)invocazioni sono molto più convenienti in quanto non dovrete sfuggire a molte cose a diversi livelli di subshell.

Queste sono solo alcune delle cose che Bash ti offre sulla tradizionale shsintassi POSIX comune .

Ma se vuoi più potenza sulla shell (non solo negli script), dai un'occhiata anche a zsh.


Bash è uno strumento molto utile, ma fai attenzione a non utilizzarlo per avviare servizi che potrebbero essere vulnerabili a un bug di scripting Bash, ad esempio access.redhat.com/security/cve/CVE-2014-6271 . Attenersi a shtali compiti.
Rick-777,

1
Rick-777 che la vulnerabilità era enormemente esagerata e secondo me il tuo commento è FUD. Se un servizio di sistema funziona sotto bash non è in alcun modo vulnerabile a quel bug. È vulnerabile a quel bug solo se interrompe un processo bash, consentendo al contempo agli utenti remoti l'accesso diretto a una o più variabili di ambiente, come in FastCGI, e anche solo su versioni senza patch di bash. Sui sistemi shcollegati bash, la vulnerabilità non verrà mitigata utilizzando sh.
Score_Under

11

In Debian e Ubuntu, /bin/shis dash, che è una shell conforme a POSIX. Se specifichi #!/bin/sh, devi limitarti alle istruzioni POSIX nel tuo script. (Il vantaggio è che dashinizia più velocemente di bash, quindi il tuo script può fare il suo lavoro in meno tempo.)

Su molti (la maggior parte?) Altri sistemi Linux, /bin/shè bash, motivo per cui molti script sono scritti con #!/bin/shla loro linea shebang anche se usano bashestensioni.

Se si desidera utilizzare le bashestensioni, è necessario specificare l'approccio più sicuro su tutti i sistemi #!/bin/bash; in questo modo dichiari esplicitamente la tua dipendenza bash. È necessario fare questo su Debian e Ubuntu. Come bonus aggiuntivo, quando avviato come si /bin/sh bashdisattiva alcune estensioni (vedere la descrizione della bashmodalità POSIX per i dettagli); quindi #!/bin/bashè necessario specificare per ottenere il massimo beneficio bash.

Su OS X /bin/bashè disponibile anche ed /bin/shè bash. Specificare #!/bin/bashfunzionerà bene anche qui.


5

Sì, arriveranno sia OSX che Linux /bin/bash. Dovresti essere perfettamente al sicuro. Tuttavia, questo non è POSIX. La shell POSIX è /bin/shsulla maggior parte (tutti?) Dei sistemi e questo è l'approccio più portatile e l'unico modo per essere compatibile con POSIX.

Si noti che mentre su molti sistemi /bin/shpunta a bash, su altri può puntare a diverse shell. È un collegamento simbolico ad esempio dashsu Debian e Ubuntu. Inoltre, anche se /bin/shè un collegamento a bash, il comportamento della shell cambia quando viene chiamato come sh(da man bash, l'enfasi mia):

Se bash viene invocato con il nome sh, cerca di imitare il comportamento di avvio delle versioni storiche di sh il più vicino possibile, rispettando allo stesso tempo lo standard POSIX. Quando viene invocato come shell di login interattiva o come shell non interattiva con l'opzione --login, tenta innanzitutto di leggere ed eseguire i comandi da / etc / profile e ~ / .profile, in questo ordine. L'opzione --noprofile può essere utilizzata per inibire questo comportamento. Quando viene invocato come shell interattiva con il nome sh, bash cerca la variabile ENV, se lo è espande il suo valore
definito e utilizza il valore espanso come nome di un file per leggere ed eseguire. Poiché una shell invocata come sh non tenta di leggere ed eseguire comandi da altri file di avvio, l'opzione --rcfile non ha alcun effetto. Una shell non interattiva invocata con il nome sh non tenta di leggere altri file di avvio. Quando viene invocato come sh, bash entra in modalità posix dopo la lettura dei file di avvio.


2

Se la compatibilità con "tutti i sistemi Unix" è un requisito assoluto - e in caso contrario, perché stai scrivendo uno script di shell? - allora sì, dovresti usarlo #! /bin/sh, perché Bash non è garantito per essere installato ovunque , figuriamoci /bin.

In realtà è molto, molto peggio di così. Se hai bisogno di compatibilità con tutti i sistemi Unix, questo include cose come Solaris e AIX che hanno congelato i loro ambienti shell verso il 1995. Ciò significa che devi usare cose come la sort +Nsintassi vecchio stile - che i sistemi più recenti sono caduti! E significa anche nessuna funzione di shell, nessuna matrice, no [[ ... ]], no ${foo#glob}, no $(( ... ))per l'aritmetica, forse la $( ... )sostituzione dei comandi senza stile, limiti superiori piccoli e non documentati su quanto grande può ottenere l'input, ...

Probabilmente si può farla franca, non preoccuparsi con quel tanto di compatibilità, ma se è nemmeno un problema, in primo luogo, vi consiglio vivamente di prendere in considerazione un linguaggio che è meno terribile di shell. L'interprete Perl di base è più probabile che sia disponibile rispetto a Bash.


Grazie. Come affermato in origine "Nel mio caso l'unico sistema operativo a cui tengo sono Ubuntu (Debian) e OSX". Questi sono gli unici 2 sistemi che ho usato (e li uso molto) negli ultimi 5 anni, quindi è per questo che sto scrivendo uno script shell che funzionerebbe solo su di essi. Non ho assolutamente bisogno di una sceneggiatura universale e dei limiti che presenterebbe.
Michael Durrant,

@MichaelDurrant In tal caso, non è necessario e non è necessario scrivere uno script di shell. Dovresti invece utilizzare uno qualsiasi dei numerosi linguaggi di scripting migliori che sono un'opzione quando non hai bisogno di portabilità totale.
zwol,
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.