¿Qué es exactamente una variable de entorno?

42

Sé que VARIABLE=valuecrea una variable de entorno y la export VARIABLE=valuepone a disposición de los procesos creados por el shell actual. envmuestra las variables de entorno actuales, pero ¿dónde viven? ¿Qué comprende una variable de entorno (o un entorno , para el caso)?

Mate
fuente

Respuestas:

29

Un entorno no es tan mágico como podría parecer. El shell lo almacena en la memoria y pasa a la execve()llamada del sistema. El proceso secundario lo hereda como un puntero de matriz llamado environ. Desde la página del execvemanual:

SINOPSIS

   #include <unistd.h>

   int execve(const char *filename, char *const argv[],
              char *const envp[]);

argves una serie de cadenas de argumentos pasados ​​al nuevo programa.
Por convención, la primera de estas cadenas debe contener el nombre de archivo asociado con el archivo que se está ejecutando. envpes una matriz de cadenas, convencionalmente de la forma clave = valor, que se pasan como entorno al nuevo programa.

La página de environ(7)manual también ofrece una idea:

SINOPSIS

   extern char **environ;

DESCRIPCIÓN

La variable environapunta a una matriz de punteros a cadenas llamadas "entorno". El último puntero en esta matriz tiene el valor NULL. (Esta variable debe declararse en el programa de usuario, pero se declara en el archivo de encabezado <unistd.h>en caso de que los archivos de encabezado provengan de libc4 o libc5, y en caso de que provengan de glibc y se haya definido _GNU_SOURCE). Esta matriz de cadenas está disponible para El proceso por la llamada exec (3) que inició el proceso.

Ambas páginas de manual de GNU coinciden con la especificación POSIX

jordanm
fuente
44
+1 probablemente valga la pena señalar que algunos miembros de la exec(3)familia (es decir, aquellos que no coinciden con exec * v) pasan ** entorno bajo las coberturas.
msw
55
Tenga en cuenta que no se trata de procesos secundarios (los procesos secundarios heredan toda la memoria de sus padres), sino de programas ejecutados (en el mismo proceso), por lo que es otra forma de pasar datos a través de una llamada al sistema execve () (que de lo contrario borra la memoria del proceso).
Stéphane Chazelas
@msw: son las exec*evariantes las que pasan explícitamente una env, en lugar de utilizar implícitamente la environvariable global. El v"vector" significa, y se refiere a los argumentos de línea de comandos pasados como una matriz (en lugar de una "lista" (función de longitud variable)) execvees una llamada al sistema, y todas las otras exec*funciones son las envolturas libc para ello.
Peter Cordes
19

Lo entendiste un poco mal: SOME_NAME=valuecrea una variable de shell (en la mayoría de los shells). export SOME_NAME=valuecrea una variable de entorno. Para bien o para mal, la mayoría de los shells Unix / Linux / * BSD usan una sintaxis idéntica para acceder a las variables de entorno y de shell.

En un sentido más amplio, un "entorno" es solo la información que acompaña a la ejecución del programa. En los programas en C, es posible encontrar el ID de proceso con una getpid()llamada, en un programa de shell se utilizaría un acceso a variables: $$. La identificación del proceso es solo parte del entorno del programa. Creo que el término "entorno" proviene de algunos de los temas más teóricos de la informática, como la ejecución de programas de modelado. Los modelos de ejecución de programas tienen un entorno "que contiene las asociaciones entre las variables y sus valores".

Y esta última, una definición más fuerte es lo que es un "entorno" para los shells Unix / Linux / * BSD: una asociación entre los nombres ("variables") y sus valores. Para la mayoría de los shells de estilo Unix, los valores son todas cadenas de caracteres, aunque eso no es tan estrictamente cierto como solía ser. Ksh, Zsh y Bash tienen variables escritas en estos días. Incluso las definiciones de funciones de shell se pueden exportar.

El uso de un entorno separado de las variables de shell simple implica el fork/execmétodo de iniciar un nuevo proceso que utilizan todos los Unixes. Cuando usted es exportun par de nombre / valor, ese par de nombre / valor estará presente en el entorno de los nuevos ejecutables, iniciados por el shell con una execve(2)llamada al sistema (generalmente siguiendo a fork(2), excepto cuando execse utilizó el comando del shell).

Después de un execve(), la main()función del nuevo binario tiene sus argumentos de línea de comandos, el entorno (almacenado como una matriz de punteros a var=valuecadenas terminada en NULL , consulte la environ(7)página del manual). Otro estado que se hereda incluye la ulimitconfiguración, el directorio de trabajo actual y cualquier descriptor de archivo abierto para el que la execve()persona que llama no haya configurado FD_CLOEXEC. El estado actual de tty (eco habilitado, modo sin formato, etc.) también podría considerarse parte del estado de ejecución heredado por un execproceso recién editado.

Consulte la bashdescripción del manual del entorno de ejecución para comandos simples (que no sean funciones integradas o de shell).

El entorno Unix es diferente de al menos algunos otros sistemas operativos: los "léxicos" de VMS podrían ser cambiados por un proceso secundario, y ese cambio era visible en el padre. Un VMS cden un proceso secundario afectaría el directorio de trabajo del padre. Al menos en algunas circunstancias, y mi memoria puede estar fallando.

Algunas variables de entorno son bien conocidos, $HOME, $PATH, $LD_LIBRARY_PATHy otros. Algunos son convencionales para un sistema de programación dado, de modo que un shell principal puede pasar mucha información de propósito especial a algún programa, como un directorio temporal específico, o un ID de usuario y contraseña que no aparecen ps -ef. Los programas CGI simples heredan mucha información del servidor web a través de variables de entorno, por ejemplo.

Bruce Ediger
fuente
1
Parecería ser un poco más complicado aún. En bash al menos SOME_NAME=value commandestablecerá la variable de entorno SOME_NAME para esa invocación de comando. Confusamente, no parece establecer la variable de shell del mismo nombre.
Samuel Edwin Ward,
2
Para ser más precisos, las variables de entorno no se heredan sino que se pasan explícitamente de un shell a los programas que genera.
msw
2
@SamuelEdwinWard la razón por la cual su SOME_NAME=value commandcomportamiento es contrario a sus expectativas es que es una sintaxis especial que significa "agregue SOME_NAME al entorno pasado al comando pero no altere las variables de este shell".
msw
1
Fascinante, el enlace al cálculo lambda / programación funcional. Esa es una conexión interesante que tiene mucho sentido.
Matt
1
Algo de esto no es del todo correcto. Por ejemplo, subcapas son subprocesos y deben ser fork()ed, pero hacer reciben (copias de) las variables de shell.
ruakh
7

Las variables de entorno en su forma más cruda son solo un conjunto de pares de nombre / valor. Como se describe en la página de manual de bash ( man 1 bash) en la sección MEDIO AMBIENTE:

   When  a  program  is invoked it is given an array of strings called the
   environment.   This  is  a  list  of  name-value  pairs,  of  the  form
   name=value.

   The  shell  provides  several  ways  to manipulate the environment.  On
   invocation, the shell scans its own environment and creates a parameter
   for  each name found, automatically marking it for export to child pro-
   cesses.  Executed commands inherit the  environment.

En términos prácticos, le permite definir un comportamiento compartido o único para los programas invocados desde el shell actual. Por ejemplo, cuando usa crontabo visudopuede definir la EDITORvariable de entorno para definir otro editor diferente al que usaría su sistema de manera predeterminada. Lo mismo puede ser cierto para cosas como el mancomando que analiza su PAGERentorno para determinar con qué programa de buscapersonas se debe usar para mostrar la salida de la página del manual.

Muchos comandos de Unix leen el entorno y, dependiendo de lo que esté configurado allí, alteran su salida / procesamiento / acción según estos. Algunos son compartidos, algunos son exclusivos del programa. La mayoría de las páginas man contienen información sobre cómo la variable de entorno tiene un efecto en el programa descrito.

Otras ilustraciones prácticas son para cosas como sistemas con varias instalaciones de Oracle en la misma plataforma. Al configurar ORACLE_HOME, todo el conjunto de comandos de Oracle (como se carga desde la PATHvariable de entorno) luego extrae configuraciones, definiciones, asignaciones y bibliotecas de debajo de ese directorio de nivel superior. Lo mismo es cierto para otros programas como Java con su JAVA_HOMEvariable de entorno.

bash en sí tiene muchas variables de entorno que pueden cambiar el comportamiento de una variedad de cosas desde el historial ( HISTSIZE, HISTFILEetc.), el tamaño de la pantalla ( COLUMNS), la finalización de pestañas ( FIGNORE, GLOBIGNORE) locale y la codificación / decodificación de caracteres ( LANG, LC_*), solicitud ( PS1.. PS4), y así sucesivamente (nuevamente busque el conocimiento de la página de manual de bash).

También puede escribir scripts / programas que utilicen sus propias variables de entorno personalizadas (para pasar configuraciones o cambiar la funcionalidad).

Drav Sloan
fuente
0

Las "variables de entorno" son un conjunto de valores dinámicos con nombre que pueden afectar la forma en que los procesos en ejecución se comportarán en una computadora.

Forman parte del entorno operativo en el que se ejecuta un proceso. Por ejemplo, un proceso en ejecución puede consultar el valor de la variable de entorno TEMP para descubrir una ubicación adecuada para almacenar archivos temporales, o la variable HOME o USERPROFILE para encontrar la estructura de directorios propiedad del usuario que ejecuta el proceso.

Más información aquí → http://en.wikipedia.org/wiki/Environment_variable .

Todo lo que quieres saber sobre las variables de entorno ... ↑

SoCalDiegoRob
fuente
1
Aunque es poco probable que estos enlaces desaparezcan, es mejor responder la pregunta aquí con texto relevante y proporcionar el enlace como una adición para la información de respaldo.
Anthon
@Anthon Creo que tienes razón y haré los cambios lo antes posible ... Gracias por el consejo ...
SoCalDiegoRob
-1

Esta respuesta requiere algo de experiencia y conocimiento de scripting de shell con los términos variable, valor, sustitución de variable, prompt, echo, kernel, shell, utilidad, sesión y proceso.

Una variable de entorno (envar) es un conjunto de variables definidas globales que pueden afectar la forma en que un determinado proceso se comportará en el sistema operativo de una computadora.

1. Una introducción ejemplar:

Sustituimos envars con letras mayúsculas$ y minúsculas . Por ejemplo: $PS1.

Podemos imprimir un envar de esta manera:

echo $PS1

$PS1contiene el valor de la solicitud de Unix. Digamos que sus valores nativos son \u \w $.

  • \u significa usuario (actual),
  • \w significa directorio de trabajo,
  • $ es bordear la solicitud.

Entonces, si lo hacemos:, echo $PS1vemos los valores de \u, \wmás el signo de dólar al final.

Podríamos cambiar el comportamiento de Unix en ese contexto, si cambiamos los valores de ese envar. Por ejemplo:

PS1="\w >"

Ahora el indicador se ve así (suponiendo que el directorio de trabajo se llame "John"):

John >

De la misma manera que podríamos hacer PS1="Hello, I'm your prompt >", entonces echo $PS1traerá:

Hello, I'm your prompt >

En Bash 4.xx, podemos imprimir TODOS los envars en el sistema con el envcomando. Sugiero ejecutar enven la terminal y echar un vistazo a la salida.

2. Cómo se muestran y manipulan estos datos:

El terminal de una sesión nos permite personalizar los envars que vienen con Bash.

Los cambios antes mencionados suelen ser temporales, y he aquí por qué:

Cada sesión (que no es una sub-sesión) es única, y varios procesos pueden ejecutarse de manera única al mismo tiempo (cada uno con su propio conjunto de envars), pero generalmente hay herencia de la sesión 0 a la sesión 1 y hacia arriba.

Los cambios que hacemos en un proceso son exclusivos y cesarán si lo cerramos sin guardarlos de alguna manera.

Entonces, ¿cómo podemos guardar estos cambios?

Hay varios tipos de formas disponibles para almacenar cambios envar, dependiendo del alcance que elijamos. Aquí hay diferentes ámbitos (niveles) para tales cambios:

  • Nivel de proceso: los envars solo están disponibles para programas en la sesión actual.
  • Nivel de exportación: los envars están disponibles para programas en la sesión actual, o en todas sus sub-sesiones.
  • Nivel global: los cambios se almacenarán para todas las sesiones (primaria y todas las subs).

Dónde se almacenan los datos envar:

Unix está construido con 3 capas principales: Kernel, shell y utilidades. AFAIK cada shell tiene sus propios envars, y estos se construyen primaria o exclusivamente en el shell.

La ubicación específica en la que cambiar globalmente estos es, por lo general, /etc/profileaunque también podemos hacerlo, por .bashrcsupuesto.

3. Crear nuevos envars:

Podemos crear nuevos envars y aquí hay un camino; a partir de Bash 4.xx no se nombra enavar nativo MESSAGE(como se dijo, los envars suelen estar en mayúsculas).

MESSAGE="Hello world!"

lo creará para nosotros, y ahora si escribimos echo $MESSAGE, obtenemos hello world!.

Si ejecutamos bashen nuestra sesión de trabajo actual (ventana), comenzaríamos una nueva sub-sesión de bash y ya no funcionará en el proceso original, a menos que ejecutemos exit.

Nota: En los sistemas operativos con un emulador de terminal (como el escritorio de Ubuntu), una sesión secundaria generalmente se ejecuta en la misma ventana, pero una sesión nueva en otra ventana no es una sesión secundaria de la existente (es un proceso adyacente ) .

Nota: ¡No use signos especiales en valores envar como! o no serán salvados.

Exportar el envar de la sesión original a todas las sub-sesiones:

Todavía podemos usar el envar creado en la primera sesión, también en la segunda, sin registrarlo en el usuario o en los archivos conf de nivel global (ver los siguientes datos). Aquí se explica cómo hacerlo:

Vaya a la sesión original (ya sea en la ventana actual u otra) y ejecute:

export MESSAGE

al exportar, no use una $señal.

Ahora se exporta a todas las sub-sesiones. Si lo hará echo $MESSAGEen una subsesión, ya sea de su usuario u otro, se imprimirá.

Tenga en cuenta que las variables internas de Shell, como por ejemplo PS1, no deben exportarse, pero si desea exportarlas por cualquier motivo y no aparecen, no ejecute bashdespués export, sino más bien bash –norc.

4. El $ PATH envar:

$PATH es el envar que los usuarios suelen cambiar más.

Si nosotros echo $PATH, vamos a ver esta transmisión:

/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Los valores impresos de este envar están separados por dos puntos (:) allí, pero aquí hay una forma potencialmente más cómoda (estos son los mismos valores):

/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

Estas son direcciones que buscar cuando ejecutamos una utilidad.

Al ejecutar which echo, obtendremos su ubicación de archivo; por ejemplo, podríamos ver que existe en /bin/echo.

En base a eso, no tenemos que escribir echo envar para ver los valores de evnar. También podemos hacer:

/bin/echo $ENVAR

El envar todavía se ejecutará, por ejemplo:

/bin/echo $HOME

Nos da

/home/User || /root

Tal como:

echo $HOME

Nos da

/home/User || /root

Nota: $HOMEse abrevia como ~.

El sistema- $ PATH relaciones, y una posible interacción del usuario:

En Bash 4.xx, cuando usamos una utilidad sin su ruta completa, el sistema usará los 6 valores mencionados anteriormente, del $PATHenvar. Entonces, comenzará desde /user/local/biny seguirá todo su contenido buscando el echoejecutable.

En este caso, se detendrá en /bin/echo, en el que, en este caso, el ejecutable reside.

Por lo tanto, la razón principal por la que podríamos personalizar el $PATHenvar es instalar archivos ejecutables que no están bajo ninguno de sus valores nativos.

Después de instalar dichos ejecutables, deberíamos establecer su $PATHvalor en consecuencia y luego podríamos trabajar con ellos.

5. Apéndice - expandiendo $PATH:

Podemos export $PATHbash sesiones secundarias (que incluye extensiones bash como WP-CLI para WordPress o Drush para Drupal) de esta manera:

export PATH="/home/John:$PATH"

Esto agregará un nuevo valor /home/Johny $PATH, luego, anexará cualquier valor nativo (justo después de los dos puntos), que se almacenan bajo la sintaxis $PATH.

Tal cambio permanente se puede hacer en la secuencia de comandos relevante, generalmente debajo /etc/profiley por el nombre .bashrc.

JohnDoea
fuente
3
Hay una gran cantidad de errores con esta respuesta: combinación de sesiones y procesos, advertencia sobre !un valor de variable de entorno que no funciona que está justo debajo de un ejemplo que muestra que funciona, una noción falsa de sub-sesiones, consejos bastante extraños sobre qué hacer después de exportar una variable de shell y una noción falsa de variables de entorno global.
JdeBP
warning about ! in an environment variable value not working that is right below an example showing it working? Por favor ejemplo.
JohnDoea
quite bizarre advice about what to do after exporting a shell variable, ¿Qué quieres decir exactamente?
JohnDoea
false notion of global environment variables, ¿Qué quieres decir exactamente?
JohnDoea