Respuesta corta
En su pregunta, el segundo comando no utiliza el .
shell incorporado ni el source
incorporado. En cambio, en realidad está ejecutando el script en un shell separado, invocando por nombre como lo haría con cualquier otro archivo ejecutable. Esto le da un conjunto separado de variables (aunque si exporta una variable en su shell principal, será una variable de entorno para cualquier proceso secundario y, por lo tanto , se incluirá en las variables de un shell secundario ). Si cambia el /
a un espacio, eso lo ejecutaría con el .
incorporado, que es equivalente a source
.
Explicación Extendida
Esta es la sintaxis del source
shell incorporado, que ejecuta el contenido de un script en el shell actual (y, por lo tanto, con las variables del shell actual):
source testenv.sh
Esta es la sintaxis del .
incorporado, que hace lo mismo que source
:
. testenv.sh
Sin embargo, esta sintaxis ejecuta el script como un archivo ejecutable, iniciando un nuevo shell para ejecutarlo:
./testenv.sh
Eso no está utilizando el .
incorporado. Más bien, .
es parte de la ruta al archivo que está ejecutando. En términos generales, puede ejecutar cualquier archivo ejecutable en un shell invocando con un nombre que contiene al menos un /
carácter. Por lo tanto, ejecutar un archivo en el directorio actual, precediéndolo por, ./
es la forma más fácil. A menos que el directorio actual esté en su PATH
, no puede ejecutar el script con el comando testenv.sh
. Esto es para evitar que las personas ejecuten accidentalmente archivos en el directorio actual cuando tengan la intención de ejecutar un comando del sistema o algún otro archivo que exista en algún directorio listado en la PATH
variable de entorno.
Como ejecutar un archivo por nombre (en lugar de con source
o .
) lo ejecuta en un nuevo shell, tendrá su propio conjunto de variables de shell. El nuevo shell hereda las variables de entorno del proceso de llamada (que en este caso es su shell interactivo) y esas variables de entorno se convierten en variables de shell en el nuevo shell. Sin embargo, para que una variable de shell se pase al nuevo shell, debe ser uno de los siguientes:
La variable de shell se ha exportado, lo que hace que sea una variable de entorno. Use el export
shell incorporado para esto. En su ejemplo, puede usar export MY_VAR=12345
para establecer y exportar la variable en un solo paso, o si ya está configurado, simplemente puede usar export MY_VAR
.
La variable de shell se establece y se pasa explícitamente para el comando que está ejecutando, lo que hace que sea una variable de entorno mientras dura el comando que se ejecuta. Esto generalmente logra que:
MY_VAR=12345 ./testenv.sh
Si se MY_VAR
trata de una variable de shell que no se ha exportado, incluso puede ejecutarse testenv.sh
con MY_VAR
pass como variable de entorno configurándola en sí misma :
MY_VAR="$MY_VAR" ./testenv.sh
./
La sintaxis de los scripts requiere una línea Hashbang para funcionar (correctamente)
Por cierto, tenga en cuenta que, cuando invocar un archivo ejecutable por el nombre que el anterior (y no con el .
o source
bombardear muebles empotrados), lo cáscara programa se utiliza para ejecutarlo se no determina normalmente por lo shell se está ejecutando desde . En lugar:
Para archivos binarios, el kernel puede configurarse para ejecutar archivos de ese tipo en particular. Examina los dos primeros bytes del archivo en busca de un "número mágico" que indique qué tipo de ejecutable binario es. Así es como se pueden ejecutar los archivos binarios ejecutables.
Esto es, por supuesto, extremadamente importante, porque un script no puede ejecutarse sin un intérprete u otro intérprete, ¡que es un binario ejecutable! Además, muchos comandos y aplicaciones son binarios compilados en lugar de scripts.
( #!
es la representación de texto del "número mágico" que indica un ejecutable de texto).
Para los archivos que se supone que se ejecutan en un shell u otro lenguaje interpretado, la primera línea se ve así:
#!/bin/sh
/bin/sh
puede ser reemplazado por cualquier otro intérprete o intérprete de comandos destinado a ejecutar el programa. Por ejemplo, un programa Python podría comenzar con la línea:
#!/usr/bin/python
Estas líneas se llaman hashbang, shebang y otros nombres similares. Vea esta entrada de FOLDOC , este artículo de Wikipedia y ¿El intérprete lee #! / Bin / sh? para más información.
Si un archivo de texto está marcado como ejecutable y lo ejecuta desde su shell (como ./filename
) pero no comienza #!
, el núcleo no puede ejecutarlo. Sin embargo, al ver que esto ha sucedido, su shell intentará ejecutarlo pasando su nombre a algún shell. Existen pocos requisitos sobre qué shell es ( "el shell ejecutará un comando equivalente a tener un shell invocado ..." ). En la práctica , algunos shells, incluido bash
*, ejecutan otra instancia de sí mismos, mientras que otros usan/bin/sh
. Le recomiendo que evite esto y use una línea hashbang en su lugar (o ejecute el script pasándolo al intérprete deseado, por ejemplo bash filename
).
* Manual de GNU Bash , 3.7.2 Búsqueda y ejecución de comandos : "Si esta ejecución falla porque el archivo no está en formato ejecutable y el archivo no es un directorio, se supone que es un script de shell y el shell lo ejecuta como se describe en scripts de Shell ".
source
es que las funciones estuvieron disponibles desde bash sin necesidad de cargar o iniciar nuevamente. Ejemplo#!/bin/bash function olakease {echo olakease;}
. Una vez que lo cargue,source file.sh
puede llamar directamenteolakease
desde bash. Realmente me gusta eso. Source se ejecuta y luego carga muchas cosas, el punto.
es solo para ejecución y es algo así como el usobash file.sh
.
tiene este comportamiento:. file.sh
ysource file.sh
hace exactamente lo mismo, incluidas las funciones de retención definidas enfile.sh
. (Tal vez estás pensando./file.sh
, lo cual es diferente. Pero eso no usa el.
incorporado; en cambio,.
es parte del camino.)Sí, te estás perdiendo algo.
Creo que estás confundiendo el '.' eso significa directorio actual, como en
./testenv.sh
y el '.' eso significasource
(que es un comando incorporado). Entonces en el caso cuando '.' significasource
que lo sería. ./testenv.sh
. ¿Tener sentido?Así que prueba esto:
fuente
./
le dice exactamente dónde está el archivo, sin él, bash buscará primero a través de PATH, luego pruebe el directorio actual si no lo encontró. Si bash se ejecuta en modo POSIX, y no proporciona una ruta al archivo (como./
), solo buscará en PATH y no podrá encontrar el archivo si el directorio actual no está en PATH.source
(y.
) en realidad comprobará $ PATH primero, a pesar de que realmente no están ejecutando el script en el sentido habitual. Mi comentario (anterior) era incorrecto.