Dove "export var = value" non è disponibile?


31

Ho capito - probabilmente su Usenet a metà degli anni '90 (!) - che il costrutto

export var=value

è un bashismo e l'espressione portatile lo è

var=value
export var

Lo sto sostenendo da anni, ma recentemente qualcuno mi ha sfidato a riguardo, e non riesco davvero a trovare alcuna documentazione a sostegno di quella che era una mia convinzione solida.

Cercare su Google "export: command not found"non sembra sollevare casi in cui qualcuno abbia effettivamente avuto questo problema, quindi anche se è genuino, immagino che non sia molto comune.

(I colpi che ricevo sembrano essere i neofiti che copiano / punteggiatura incollato, e si è conclusa con 'export: command not foundo qualcosa del genere, o intenzione di usare exportcon sudoe newbie csh. Utenti che tentano di utilizzare la sintassi Bourne shell)

Posso sicuramente dire che funziona su OS X e su varie distribuzioni Linux, comprese quelle dove si shtrova dash.

sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

Nel mondo di oggi, è sicuro dire che export var=valueè sicuro da usare?

Mi piacerebbe capire quali sono le conseguenze. Se non è portabile su v7 "Bourne classic", non è altro che curiosità. Se ci sono sistemi di produzione in cui la shell non riesce davvero a far fronte a questa sintassi, sarebbe utile saperlo.


2
grazie ho finalmente capito perché vedo così spesso ciò che pensavo fosse inutile: var = value; export var
Thorsten Staerk

2
Ci sono ancora alcune scatole di Solaris che saltano in giro, e quelle sono notoriamente frugali nei loro strumenti standard; dall'altra parte dello spettro, non busyboxarriva il suo guscio minimo? (Non sono in grado di provare bene neanche questo secondo.)
Ulrich Schwarz,

Grazie Ulrich, Solaris potrebbe essere il colpevole del perché questa lunga sintassi è ancora in circolazione.
Thorsten Staerk,

Risposte:


20
export foo=bar

non era supportato dalla shell Bourne (una vecchia shell degli anni '70 da cui shderivano implementazioni moderne come ash / bash / ksh / yash / zsh). Questo è stato introdotto da ksh.

Nella shell Bourne, faresti:

foo=bar export foo

o:

foo=bar; export foo

o con set -k:

export foo foo=bar

Ora, il comportamento di:

export foo=bar

varia da shell a shell.

Il problema è che le assegnazioni e gli argomenti dei comandi semplici vengono analizzati e interpretati in modo diverso.

Quanto foo=barsopra è interpretato da alcune shell come argomento di comando e da altri come assegnazione (a volte).

Per esempio,

a='b c'
export d=$a

è interpretato come:

'export' 'd=b' 'c'

con alcune shell ( ash, versioni precedenti di zsh(in emulazione sh), yash) e:

'export' 'd=b c'

negli altri ( bash, ksh).

Mentre

export \d=$a

o

var=d
export $var=$a

sarebbe interpretato lo stesso in tutte le shell (come 'export' 'd=b' 'c' ) perché quella barra rovesciata o il simbolo del dollaro blocca quelle shell che lo supportano per considerare quegli argomenti come assegnazioni.

Se export stesso viene citato o il risultato di una certa espansione (anche in parte), a seconda della shell, smetterebbe anche di ricevere il trattamento speciale.

Vedi " Sono necessarie le virgolette per l'assegnazione delle variabili locali? " Per ulteriori dettagli al riguardo.

La sintassi di Bourne però:

d=$a; export d

viene interpretato allo stesso modo da tutte le shell senza ambiguità ( d=$a export dfunzionerebbe anche nelle shell Bourne e POSIX compatibili ma non nelle versioni recenti di a zshmeno che in shemulazione).

Può andare molto peggio di così. Si veda ad esempio quella recente discussione subash quando sono coinvolte le matrici.

(IMO, è stato un errore introdurre quella funzione ).


Sono rimasto sorpreso dal fatto che il punto e virgola non sia richiesto foo=bar export foo, come l'avevo sempre visto lì. So che l'esportazione è integrata, ma perché si foo=bar; foo=baz export foo; echo $foocomporta diversamente foo=bar; foo=baz /bin/cat /dev/null; echo $foo?
jrw32982 supporta Monica il

3
@ jrw32982, perché è incorporato. Lo ottieni ancora nelle moderne shell POSIX ma solo per builtin speciali che lo exportsono.
Stéphane Chazelas,

Anche se discute declare, no export, consiglio a chiunque abbia a cuore la sicurezza di leggere la discussione al link che StéphaneChazelas ha fornito a bash.bugs .
Giovanni 1024,

Bella risposta! Ma ci è voluto molto tempo per essere d=$a export dinterpretato allo stesso modo da tutte le shell senza ambiguità ;-)
Conny

@conny, d=$a export dnon funziona più in zsh, quindi ho aggiornato la risposta. Vedi modifica.
Stéphane Chazelas,

28

Non è un basismo ma una sintassi conforme a POSIX. In realtà è iniziato come un kshism molto tempo fa e in seguito è stato adottato da quasi tutte le shell basate sulla sintassi di Bourne. L'unica nota eccezione è /bin/shsu Solaris 10 e precedenti che si attacca alla sintassi della shell Bourne legacy. Si spera che Solaris 11 usi una shell conforme a POSIX come /bin/sh.

A proposito, exportera già un comando incorporato nella shell Bourne legacy, quindi cercare su Google export: command not foundera fuorviante.

Ecco il comportamento della shell Bourne legacy quando exportcombinato con un'influenza:

$ export var=22
var=22: is not an identifier

Per i nostalgici, il codice sorgente di questa shell Bourne originale è disponibile e può essere compilato per la maggior parte delle distribuzioni Unix e Linux.


Mille grazie per la visione storica e il messaggio di errore corretto per Google! Evidente in retrospettiva, arrossisce ...
tripleee

4
Questo non è il codice sorgente della shell Bourne originale, è un sh OpenSolaris modificato. È il guscio di Bourne ma dopo aver subito decenni di evoluzione. La shell Bourne originale, spedita con Unix V7, è reperibile presso la Unix Heritage Society
Stéphane Chazelas,

1
@ StéphaneChazelas A rigor di termini, hai ragione come al solito. Si noti tuttavia che non ho scritto "la shell Bourne originale" ma "questa shell Bourne originale" poiché mi riferivo alla shell utilizzata da Solaris 10 e al suo codice sorgente che può essere compilato su piattaforme moderne. Si noti inoltre che la shell Bourne ha avuto diverse funzionalità aggiunte tra il 1977 e il 1989, ma che ha sostanzialmente smesso di evolversi (porting esterno / adattamento a piattaforme più recenti e correzioni di bug) negli ultimi 25 anni circa.
jlliagre,
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.