Caracteres permitidos en nombres de variables de entorno Linux

143

¿Qué caracteres están permitidos en los nombres de variables de entorno de Linux? Mi búsqueda superficial de páginas de manual y la web solo produjo información sobre cómo trabajar con variables, pero no qué nombres están permitidos.

Tengo un programa Java que requiere una variable de entorno definida que contiene un punto, como com.example.fancyproperty. Con Windows puedo configurar esa variable, pero no tuve suerte configurándola en Linux (probado en SuSE y Ubuntu). ¿Se permite incluso ese nombre de variable?

Christian Semrau
fuente
3
Afortunadamente, descubrí que el programa está tan contento con una propiedad del sistema Java (declarada con una -Dopción de línea de comando), por lo que funciona ahora. Obviamente, el programa se ve en ambos conjuntos de variables sin decirme. Pero aún tengo curiosidad sobre qué nombres de variables de entorno están permitidos.
Christian Semrau
@AleksandrDubinsky Lo eliminé. Esto es similar, pero la definición de alias no es exactamente las variables de entorno stackoverflow.com/questions/24690640/…
Lima
1
Si está utilizando Spring , entonces el SystemEnvironmentPropertySource predeterminado también buscará com_example_fancypropertyy COM_EXAMPLE_FANCYPROPERTY.
Aleksandr Dubinsky

Respuestas:

203

Del grupo abierto :

Estas cadenas tienen la forma nombre = valor; los nombres no deben contener el carácter '='. Para que los valores sean portables en los sistemas que cumplen con IEEE Std 1003.1-2001, el valor debe estar compuesto por caracteres del conjunto de caracteres portátiles ( excepto NUL y como se indica a continuación ).

Por lo tanto, los nombres pueden contener cualquier carácter excepto = y NUL, pero:

Los nombres de las variables de entorno utilizados por las utilidades en el volumen Shell y Utilities de IEEE Std 1003.1-2001 consisten únicamente en letras mayúsculas, dígitos y el '_' (guión bajo) de los caracteres definidos en Portable Character Set y no comienzan con un dígito . Otros caracteres pueden ser permitidos por una implementación; las aplicaciones tolerarán la presencia de tales nombres.

Entonces, aunque los nombres pueden ser válidos, es posible que su shell no admita nada más que letras, números y guiones bajos.

Robert Gamble
fuente
8
Solo verificando: la segunda cita no es normativa: solo observa que las variables que POSIX define como especiales para sus utilidades son [a-zA-Z_][a-zA-Z0-9_]*(lo que sugiere implícitamente que este formulario es más sensato), pero la especificación real (cita 1) requiere que toda la implementación admita cualquier cosa menos =y NUL?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Además, el "conjunto de caracteres portátil" pubs.opengroup.org/onlinepubs/000095399/basedefs/… contiene cosas como espacios y no imprimibles: ¿podemos usar esas cosas o no?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Esto es exactamente lo que observo. A Shell no le gustan los caracteres especiales como parte de un nombre de variable. Sin embargo, cuando un programa o script (por ejemplo, java o perl) inicializa una variable con caracteres especiales en su nombre y llama a otro ejecutable (un proceso secundario), el último ejecutable puede acceder a esa variable sin problemas.
oᴉɹǝɥɔ
1
@checksum, MAYÚSCULAS se especifica explícitamente para nombres de variables con significado para las herramientas especificadas por POSIX, incluido el shell; los nombres con al menos un carácter en minúscula están explícitamente reservados para uso de la aplicación. Por lo tanto, la mejor práctica es incluir al menos un carácter en minúscula en los nombres de las variables de las aplicaciones para garantizar que no se sobrescriba involuntariamente (ya que al configurar una variable de shell se sobrescribirá cualquier variable de entorno con un nombre similar) una variable con significado para el sistema. Ver pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy el
2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, puede usarlos en variables de entorno; no puede usarlos en variables de shell, y no se garantiza que esas variables de entorno sean accesibles desde el shell.
Charles Duffy
37

La sección de estándares POSIX en shells de IEEE Std 1003.1-2008 / IEEE POSIX P1003.2 / ISO 9945.2 Shell y herramientas estándar no define la convención léxica para nombres de variables, sin embargo, una mirada superficial a la fuente revela que usa algo similar a

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

(Editar: Se agregó subrayado perdido en la segunda clase de caracteres).

Una nota rápida, ya que algunos shells no admiten el + en la expresión regular, una expresión regular potencialmente más portátil puede ser:

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

Aiden Bell
fuente
44
Gracias Aiden Creo que falta un guión bajo en el segundo conjunto de corchetes: probablemente debería leer: [a-zA-Z_][a-zA-Z0-9_]* Para aquellos como yo que encuentran la referencia a bash-4.1 un poco vaga (616'000 líneas de código), aquí hay algunos consejos para encuentre las líneas de código relevantes: subst.c: param_expand(), in the default case-> general.h:/ * Defina exactamente en qué consiste un identificador de shell legal. * / #define legal_variable_starter (c) (ISALPHA (c) || ​​(c == ' ')) #define legal_variable_char (c) (ISALNUM (c) || ​​c == ' ')
Chris
3
No necesitas esa ventaja en la primera clase de personaje.
scravy
2
@scravy cierto, aunque tomé la expresión regular de la fuente, así que voy a mantener el +.
Aiden Bell
44
POSIX define: 3.231 Nombre a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit .
No se encuentra en la sección de shell, pero existen estándares POSIX que incluyen convenciones para la denominación de variables de entorno (y en realidad discuten nombres que están reservados para el uso de shell). Ver pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy el
12

Mi prueba rápida mostró que básicamente siguen las mismas reglas que los nombres de variables C, es decir

  1. az, AZ _y 0-9
  2. NO puede comenzar con un número

Entonces esto excluye .dentro de ellos. Cualquier nombre de variable ilegal se acredita con unknown command.

Esto se probó en ZSH, que es principalmente compatible con BASH.

LukeN
fuente
6

Depende de lo que quieras decir con 'permitido'.

Ignorando Windows para el nonce:

El entorno es una serie de cadenas, pasadas a la función principal de un programa. Si lee execve (2), no verá requisitos o límites en estas cadenas que no sean terminación nula.

Por convención, cada cadena consta de NOMBRE = valor. No existe una convención de citas, por lo que no puede tener un '=' en el nombre de esta convención.

Los humanos normales establecen estas cadenas discutiéndolas con su caparazón. Cada shell tiene sus propias ideas de lo que son variables NAME válidas, por lo que debe leer la página del manual del shell del momento para ver qué piensa.

En general, cosas como com.baseball.spit = fleagh son propiedades del sistema Java, y si algún programa Java está dispuesto a recurrir al entorno, es mejor especificarlos con -D.

bmargulies
fuente
Debería haber llegado antes a la conclusión de que la variable está formateada como una propiedad del sistema Java, en lugar de tratar de establecerla como una variable de entorno.
Christian Semrau
4

SI, PUEDES HACERLO.

Usa execy envordena para implementar esta escena.

Dispositivo de prueba en Docker

docker run -it --rm alpine:3.10

Ejecutar comando en contenedor:

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

Verifique las variables de entorno:

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=/

Use ps auxpara verificar que el PID no haya cambiado

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

Use pythonpara verificar la variable de entorno

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

SALIDA es happy-variable-name.

¿Qué ocurre?

  1. Ejecutiva de llamada de Shell integrada
  2. Ejecutar el intérprete de comandos integrado de shell syscall.exec crea el proceso 'env' para reemplazar el intérprete de comandos actual
  3. proceso env llame a syscall.execvp cree el proceso '/ bin / sh' para reemplazar el proceso env

De otra manera

  • Imagen de Docker

Si está usando docker, puede establecer variables en Dockerfile

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

Si está utilizando kubernetes, puede configurar variables mediante 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

Implementar pod kubectl apply -f test.yaml

Verificar kubectl logs foobarsalida:

xx.ff-bar=1234

ConfigMap permite '-', '_' o '.'

Celoso
fuente
0

Si bien la mayoría de los shell no permitirán establecer variables de entorno (como se menciona en otras respuestas), si lo necesita, puede ejecutar otros programas con variables de entorno no estándar utilizando env(1).

Por ejemplo, borrar todo el entorno y establecer el Strange.Env:Varvalor foo, y ejecutar el programa perl que lo imprime:

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

imprimirá

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