Respuestas:
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 execve
manual:
SINOPSIS
#include <unistd.h> int execve(const char *filename, char *const argv[], char *const envp[]);
argv
es 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.envp
es 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
environ
apunta a una matriz de punteros a cadenas llamadas "entorno". El último puntero en esta matriz tiene el valorNULL
. (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
exec*e
variantes las que pasan explícitamente una env, en lugar de utilizar implícitamente la environ
variable 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)) execve
es una llamada al sistema, y todas las otras exec*
funciones son las envolturas libc para ello.
Lo entendiste un poco mal: SOME_NAME=value
crea una variable de shell (en la mayoría de los shells). export SOME_NAME=value
crea 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/exec
método de iniciar un nuevo proceso que utilizan todos los Unixes. Cuando usted es export
un 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 exec
se 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=value
cadenas terminada en NULL , consulte la environ(7)
página del manual). Otro estado que se hereda incluye la ulimit
configuració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 exec
proceso recién editado.
Consulte la bash
descripció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 cd
en 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_PATH
y 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.
SOME_NAME=value command
establecerá la variable de entorno SOME_NAME para esa invocación de comando. Confusamente, no parece establecer la variable de shell del mismo nombre.
SOME_NAME=value command
comportamiento 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".
fork()
ed, pero hacer reciben (copias de) las variables de shell.
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 crontab
o visudo
puede definir la EDITOR
variable 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 man
comando que analiza su PAGER
entorno 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 PATH
variable 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_HOME
variable de entorno.
bash en sí tiene muchas variables de entorno que pueden cambiar el comportamiento de una variedad de cosas desde el historial ( HISTSIZE
, HISTFILE
etc.), 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).
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 ... ↑
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.
Sustituimos envars con letras mayúsculas$
y minúsculas . Por ejemplo: $PS1
.
Podemos imprimir un envar de esta manera:
echo $PS1
$PS1
contiene 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 $PS1
vemos los valores de \u
, \w
má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 $PS1
traerá:
Hello, I'm your prompt >
En Bash 4.xx, podemos imprimir TODOS los envars en el sistema con el env
comando. Sugiero ejecutar env
en la terminal y echar un vistazo a la salida.
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.
Hay varios tipos de formas disponibles para almacenar cambios envar, dependiendo del alcance que elijamos. Aquí hay diferentes ámbitos (niveles) para tales cambios:
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/profile
aunque también podemos hacerlo, por .bashrc
supuesto.
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 bash
en 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.
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 $MESSAGE
en 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 bash
después export
, sino más bien bash –norc
.
$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: $HOME
se abrevia como ~
.
En Bash 4.xx, cuando usamos una utilidad sin su ruta completa, el sistema usará los 6 valores mencionados anteriormente, del $PATH
envar. Entonces, comenzará desde /user/local/bin
y seguirá todo su contenido buscando el echo
ejecutable.
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 $PATH
envar es instalar archivos ejecutables que no están bajo ninguno de sus valores nativos.
Después de instalar dichos ejecutables, deberíamos establecer su $PATH
valor en consecuencia y luego podríamos trabajar con ellos.
$PATH
:Podemos export $PATH
bash 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/John
y $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/profile
y por el nombre .bashrc
.
!
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.
warning about ! in an environment variable value not working that is right below an example showing it working
? Por favor ejemplo.
quite bizarre advice about what to do after exporting a shell variable
, ¿Qué quieres decir exactamente?
false notion of global environment variables
, ¿Qué quieres decir exactamente?
exec(3)
familia (es decir, aquellos que no coinciden con exec * v) pasan ** entorno bajo las coberturas.