Où «export var = value» n'est pas disponible?

31

J'ai compris - probablement sur Usenet au milieu des années 1990 (!) - que la construction

export var=value

est un bashisme, et que l'expression portable est

var=value
export var

Je préconise cela depuis des années, mais récemment, quelqu'un m'a contesté à ce sujet, et je ne trouve vraiment aucune documentation pour sauvegarder ce qui était une croyance solide.

La recherche sur Google "export: command not found"ne semble pas évoquer de cas où quelqu'un a réellement eu ce problème, donc même si c'est authentique, je suppose que ce n'est pas très courant.

(Les hits que je reçois semblent être des débutants qui copient / collent la ponctuation, et se sont retrouvés avec 'export: command not foundou quelque chose comme ça , ou qui essaient d'utiliser exportavec sudo; et les cshutilisateurs débutants essayant d'utiliser la syntaxe du shell Bourne.)

Je peux certainement dire que cela fonctionne sur OS X et sur diverses distributions Linux, y compris celles où il se shtrouve dash.

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

Dans le monde d'aujourd'hui, est-il sûr de dire que son utilisation export var=valueest sûre?

J'aimerais comprendre quelles en sont les conséquences. Si ce n'est pas portable pour la v7 "Bourne classic", ce n'est guère plus qu'une anecdote. S'il existe des systèmes de production où le shell ne peut vraiment pas faire face à cette syntaxe, ce serait utile de le savoir.

tripleee
la source
2
merci j'ai enfin compris pourquoi je vois si souvent la chose que je pensais inutile: var = value; export var
Thorsten Staerk
2
Il y a encore quelques boîtes Solaris qui tournent, et celles-ci sont notoirement sobres dans leurs outils standard; à l'autre bout du spectre, ne busyboxvient pas avec sa propre coquille minimale? (Je ne suis pas en mesure d'essayer non plus cette seconde.)
Ulrich Schwarz
Merci Ulrich, Solaris pourrait bien être le coupable pourquoi cette longue syntaxe existe toujours.
Thorsten Staerk

Réponses:

20
export foo=bar

n'était pas supporté par le shell Bourne (un ancien shell des années 70 dont shdérivent des implémentations modernes comme ash / bash / ksh / yash / zsh). Cela a été présenté par ksh.

Dans le shell Bourne, vous feriez:

foo=bar export foo

ou:

foo=bar; export foo

ou avec set -k:

export foo foo=bar

Maintenant, le comportement de:

export foo=bar

varie d'une coquille à l'autre.

Le problème est que les affectations et les arguments de commande simples sont analysés et interprétés différemment.

Ce qui foo=barprécède est interprété par certains shells comme un argument de commande et par d'autres comme une affectation (parfois).

Par exemple,

a='b c'
export d=$a

est interprété comme:

'export' 'd=b' 'c'

avec certains shells ( ash, anciennes versions de zsh(en émulation sh), yash) et:

'export' 'd=b c'

dans les autres ( bash, ksh).

Tandis que

export \d=$a

ou

var=d
export $var=$a

serait interprété de la même manière dans tous les shells (as 'export' 'd=b' 'c') car cette barre oblique inversée ou ce signe dollar empêche les shells qui le prennent en charge de considérer ces arguments comme des affectations.

Si exportelle-même est citée ou résulte d'une certaine expansion (même partielle), selon la coque, elle cesserait également de bénéficier du traitement spécial.

Voir "Des citations sont-elles nécessaires pour l'affectation des variables locales? " Pour plus de détails à ce sujet.

La syntaxe Bourne cependant:

d=$a; export d

est interprété de la même manière par tous les shells sans ambiguïté ( d=$a export dfonctionnerait également dans le shell Bourne et les shells compatibles POSIX mais pas dans les versions récentes de zshsauf en shémulation).

Cela peut devenir bien pire que cela. Voir par exemple cette récente discussion sur lebash moment où les tableaux sont impliqués.

(OMI, c'était une erreur d'introduire cette fonctionnalité ).

Stéphane Chazelas
la source
J'ai été surpris que le point-virgule ne soit pas requis dans foo=bar export foo, comme je l'avais toujours vu là-bas. Je sais que l'exportation est une fonction intégrée, mais pourquoi foo=bar; foo=baz export foo; echo $foose comporte-t-elle différemment foo=bar; foo=baz /bin/cat /dev/null; echo $foo?
jrw32982 prend en charge Monica
3
@ jrw32982, car il s'agit d'une fonction intégrée. Vous obtenez toujours cela dans les shells POSIX modernes, mais seulement pour les buildins spéciaux qui le exportsont.
Stéphane Chazelas
Bien qu'il discute declare, non export, je recommande à quiconque se soucie de la sécurité de lire la discussion sur le lien que StéphaneChazelas a fourni à bash.bugs .
John1024
Très bonne réponse! Mais il a fallu beaucoup de temps pour s'y rendre d=$a export dest interprété de la même manière par tous les obus sans ambiguïté ;-)
conny
@conny, d=$a export dne fonctionne plus zsh, j'ai donc mis à jour la réponse. Voir modifier.
Stéphane Chazelas
28

Ce n'est pas un bashisme mais une syntaxe compatible POSIX. Il a en fait commencé comme kshism il y a assez longtemps et a ensuite été adopté par presque tous les shells basés sur la syntaxe Bourne. La seule exception notoire /bin/shconcerne Solaris 10 et les versions antérieures, qui restent fidèles à la syntaxe héritée du shell Bourne. Espérons que Solaris 11 utilise un shell compatible POSIX en tant que /bin/sh.

Soit dit en passant, exportétait déjà une commande intégrée dans le shell Bourne hérité, donc googler export: command not foundétait trompeur.

Voici le comportement hérité du shell Bourne lorsqu'il exportest combiné avec une affectation:

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

Pour les nostalgiques, le code source de ce shell Bourne original est disponible et peut être compilé pour la plupart des distributions Unix et Linux.

jlliagre
la source
Merci beaucoup pour l'historique et le message d'erreur correct à google! Rétrospectivement évident, blush ...
tripleee
4
Ce n'est pas le code source du shell Bourne d'origine, c'est un sh OpenSolaris modifié. Il s'agit de la coquille de Bourne mais après avoir subi des décennies d'évolution. Le shell Bourne d'origine, tel qu'expédié avec Unix V7, peut être trouvé à la Unix Heritage Society
Stéphane Chazelas
1
@ StéphaneChazelas À strictement parler, vous avez comme d'habitude raison. Notez cependant que je n'ai pas écrit "le shell Bourne original" mais "ce shell Bourne original" car je faisais référence au shell utilisé par Solaris 10 et à son code source qui peut être compilé sur les plateformes modernes. Notez également que le shell Bourne a eu plusieurs fonctionnalités ajoutées entre 1977 et 1989, mais a essentiellement cessé d'évoluer (hors portage / adaptation aux nouvelles plates-formes et corrections de bugs) au cours des 25 dernières années.
2015