Caractères autorisés dans les noms de variables d'environnement Linux

143

Quels caractères sont autorisés dans les noms de variables d'environnement Linux? Ma recherche rapide des pages de manuel et du Web n'a produit que des informations sur la façon de travailler avec des variables, mais pas sur les noms autorisés.

J'ai un programme Java qui nécessite une variable d'environnement définie contenant un point, comme com.example.fancyproperty. Avec Windows, je peux définir cette variable, mais je n'ai pas eu de chance de la définir sous Linux (essayé dans SuSE et Ubuntu). Ce nom de variable est-il même autorisé?

Christian Semrau
la source
3
Heureusement, j'ai trouvé que le programme est tout aussi satisfait d'une propriété système Java (déclarée avec une -Doption de ligne de commande), donc cela fonctionne maintenant. Évidemment, le programme regarde dans les deux ensembles de variables sans me le dire. Mais je suis toujours curieux de savoir quels noms de variables d'environnement sont autorisés.
Christian Semrau
@AleksandrDubinsky Je l'ai supprimé. C'est similaire, mais à propos de la définition d'alias pas exactement les variables d'environnement stackoverflow.com/questions/24690640/…
Lime
1
Si vous utilisez Spring , le SystemEnvironmentPropertySource par défaut recherchera également com_example_fancypropertyet COM_EXAMPLE_FANCYPROPERTY.
Aleksandr Dubinsky

Réponses:

203

Du groupe ouvert :

Ces chaînes ont la forme nom = valeur; les noms ne doivent pas contenir le caractère «=». Pour que les valeurs soient portables sur des systèmes conformes à la norme IEEE 1003.1-2001, la valeur doit être composée de caractères du jeu de caractères portable ( sauf NUL et comme indiqué ci-dessous ).

Les noms peuvent donc contenir n'importe quel caractère sauf = et NUL, mais:

Les noms de variables d'environnement utilisés par les utilitaires dans le volume Shell and Utilities de IEEE Std 1003.1-2001 se composent uniquement de lettres majuscules, de chiffres et du '_' (trait de soulignement) parmi les caractères définis dans le jeu de caractères portable et ne commencent pas par un chiffre . D'autres caractères peuvent être autorisés par une implémentation; les demandes doivent tolérer la présence de ces noms.

Ainsi, bien que les noms soient valides, votre shell peut ne prendre en charge rien d'autre que les lettres, les chiffres et les traits de soulignement.

Robert Gamble
la source
8
Juste vérifier: la deuxième citation n'est pas normative: elle observe simplement que les variables que POSIX définit comme spéciales pour ses utilitaires sont [a-zA-Z_][a-zA-Z0-9_]*(suggérant implicitement que cette forme est plus saine), mais la spécification réelle (citation 1) nécessite que toute implémentation prenne en charge tout sauf =et NUL?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
De plus, le "jeu de caractères portable" pubs.opengroup.org/onlinepubs/000095399/basedefs/ ... contient des éléments tels que des espaces et des éléments non imprimables: pouvons-nous utiliser ces éléments ou pas?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
C'est exactement ce que j'observe. Shell n'aime pas les caractères spéciaux dans le cadre d'un nom de variable. Cependant, lorsqu'un programme ou un script (par exemple java ou perl) initialise une variable avec des caractères spéciaux dans son nom et appelle un autre exécutable (un processus enfant), ce dernier exécutable peut accéder à cette variable sans problème.
oᴉɹǝɥɔ
1
@checksum, UPPERCASE est explicitement spécifié pour les noms de variables ayant une signification pour les outils spécifiés par POSIX, y compris le shell; les noms comportant au moins un caractère minuscule sont explicitement réservés à l'usage de l'application. Ainsi, la meilleure pratique consiste en fait à inclure au moins un caractère minuscule dans les noms de variable de vos applications pour vous assurer de ne pas écraser involontairement (car la définition d'une variable shell écrasera toute variable d'environnement portant le même nom) une variable avec une signification à le système. Voir pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy
2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, vous pouvez les utiliser dans des variables d'environnement; vous ne pouvez pas les utiliser dans des variables shell, et ces variables d'environnement ne sont pas garanties d'être accessibles depuis le shell.
Charles Duffy
37

La section des standards POSIX sur les shells de la norme IEEE Std 1003.1-2008 / IEEE POSIX P1003.2 / ISO 9945.2 Shell and Tools ne définit pas la convention lexicale pour les noms de variables, mais un rapide coup d'œil à la source révèle qu'elle utilise quelque chose de similaire à

[a-zA-Z_]+[a-zA-Z0-9_]*

(Modifier: ajout de trait de soulignement manquant dans la 2e classe de caractères.)

Une note rapide, comme certains shells ne prennent pas en charge le + dans les regex, une regex potentiellement plus portable peut être:

[a-zA-Z_]{1,}[a-zA-Z0-9_]{0,}

Aiden Bell
la source
4
Merci, Aiden. Je pense qu'il manque un trait de soulignement dans le deuxième ensemble de crochets: Il devrait probablement lire: [a-zA-Z_][a-zA-Z0-9_]* Pour ceux comme moi qui trouvent la référence à bash-4.1 un peu vague (616'000 lignes de code), voici quelques conseils pour trouver les lignes de code pertinentes: subst.c: param_expand(), in the default case-> general.h:/ * Définir exactement en quoi consiste un identifiant de shell légal. * / #define legal_variable_starter (c) (ISALPHA (c) || ​​(c == ' ')) #define legal_variable_char (c) (ISALNUM (c) || ​​c == ' ')
Chris
3
Vous n'avez pas besoin de ce plus dans la première classe de caractères.
scravy
2
@scravy true, même si j'ai pris l'expression rationnelle de la source, je vais donc garder le + dedans.
Aiden Bell
4
POSIX définit: 3.231 Nom a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit .
Pas dans la section shell, mais il existe absolument des standards POSIX qui incluent des conventions pour la dénomination des variables d'environnement (et qui traitent en fait des noms réservés à l'utilisation du shell). Voir pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy
12

Mes tests rapides ont montré qu'ils suivent fondamentalement les mêmes règles que les noms de variables C, à savoir

  1. az, AZ, _ et 0-9
  2. NE DOIT PAS commencer par un nombre

Donc, cela exclut à l' .intérieur d'eux. Tout nom de variable non autorisé est crédité unknown command.

Cela a été testé dans ZSH, qui est principalement compatible BASH.

LukeN
la source
6

Cela dépend de ce que vous entendez par «autorisé».

Ignorer Windows pour le nonce:

L'environnement est un tableau de chaînes, passé à la fonction principale d'un programme. Si vous lisez execve (2), vous ne verrez aucune exigence ou limite sur ces chaînes autres que null-terminaison.

Par convention, chaque chaîne se compose de NOM = valeur. Il n'y a pas de convention de citation, vous ne pouvez donc pas avoir de «=» dans le nom de cette convention.

Les humains normaux fixent ces chaînes en les discutant avec leur coquille. Chaque shell a ses propres idées de ce que sont des NOM de variables valides, vous devez donc lire la page de manuel du shell-of-the-moment pour voir ce qu'il pense.

Généralement, des choses comme com.baseball.spit = fleagh sont des propriétés système Java, et que certains programmes Java soient prêts à revenir à l'environnement, il est préférable de les spécifier avec -D.

bmargulies
la source
J'aurais dû arriver plus tôt à la conclusion que la variable est formatée comme une propriété système Java, au lieu d'essayer de la définir comme variable d'environnement.
Christian Semrau
5

Cela dépend de la coque. J'imagine que vous utilisez bash par défaut, auquel cas les lettres, les chiffres et les traits de soulignement sont autorisés, mais vous ne pouvez pas commencer le nom de la variable par un nombre. Depuis Bash v.3, les points ne sont pas autorisés dans les noms de variables .

ire_and_curses
la source
4

OUI TU PEUX LE FAIRE.

Utilisez la commande execet envpour implémenter cette scène.

Appareil de test dans Docker

docker run -it --rm alpine:3.10

Exécutez la commande dans le conteneur:

exec env spring.application_name=happy-variable-name ${SHELL:-/bin/sh}

Vérifiez les variables d'environnement:

HOSTNAME=bd0bccfdc53b
SHLVL=2
HOME=/root
spring.application_name=happy-variable-name
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

Utilisez ps auxpour vérifier que le PID n'a pas été modifié

PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
   12 root      0:00 ps aux

Utilisez pythonpour vérifier la variable d'environnement

apk add python
python -c 'import os; print(os.environ["spring.application_name"])'

OUTPUT est happy-variable-name.

Qu'est-ce qui se passe?

  1. Exécuteur intégré d'appel Shell
  2. Le shell intégré exécute l'appel syscall.exec crée le processus 'env' pour remplacer le shell actuel
  3. env processus appel syscall.execvp create process '/ bin / sh' pour remplacer le processus env

Autrement

  • Image Docker

Si vous utilisez docker, vous pouvez définir une variable dans Dockerfile

FROM busybox
ENV xx.f%^&*()$#ff=1234
  • Configuration de Kubernetes

Si vous utilisez kubernetes, vous pouvez définir la variable par ConfigMap

test.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: foo-config
data:
  "xx.ff-bar": "1234"

---
apiVersion: v1
kind: Pod
metadata:
  name: foobar
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - configMapRef:
          name: foo-config
  restartPolicy: Never

Déployer le pod kubectl apply -f test.yaml

Vérifiez la kubectl logs foobarsortie:

xx.ff-bar=1234

ConfigMap autorise '-', '_' ou '.'

Zélique
la source
0

Bien que la plupart des shell ne permettent pas de définir des variables d'environnement (comme mentionné dans d'autres réponses), si vous en avez besoin, vous pouvez exécuter d'autres programmes avec des variables d'environnement non standard en utilisant env(1) .

Par exemple, effacer tout l'environnement et mettre Strange.Env:Varà valeur foo, et exécuter le programme perl qui l'imprime:

env -i Strange.Env:Var=foo perl -MData::Dumper -E 'say Dumper(\%ENV)'

va imprimer

$VAR1 = {
          'Strange.Env:Var' => 'foo'
        };
Matija Nalis
la source