¿Cuál es la diferencia entre ejecutar un script de Bash y abastecerse de él?
¿Cuál es la diferencia entre ejecutar un script Bash como A y abastecer un script Bash como B?
A
> ./myscript
B
> source myscript
Ejecutar un script ejecutará los comandos en el proceso de shell actual.
Ejecutar un script ejecutará los comandos en un nuevo proceso del shell.
Use source si quiere que el script cambie el entorno en su shell actual. use execute en caso contrario.
Si todavía está confundido, por favor siga leyendo.
Para aclarar algunas confusiones comunes sobre la sintaxis de ejecutar y la sintaxis de source:
./myscript
Esto ejecutará myscript
siempre que el archivo sea ejecutable y se encuentre en el directorio actual. El punto y la barra (./
) indican el directorio actual. Esto es necesario porque el directorio actual normalmente no está (y normalmente no debería estar) en $PATH
.
myscript
Esto ejecutará myscript
si el archivo es ejecutable y se encuentra en algún directorio en $PATH
.
source myscript
Esto será fuente myscript
. No es necesario que el archivo sea ejecutable, pero debe ser un script de shell válido. El archivo puede estar en el directorio actual o en un directorio en $PATH
.
. myscript
Esto también será fuente myscript
. Esta “ortografía” es la oficial definida por POSIX . Bash definió source
como un alias del punto.
Considere myscript.sh
con el siguiente contenido:
#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD
Antes de ejecutar el script primero comprobamos el entorno actual:
$ env | grep FOO
$ echo $PWD
/home/lesmana
La variable FOO
no está definida y estamos en el directorio home.
Ahora ejecutamos el archivo:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Comprueba de nuevo el entorno:
$ env | grep FOO
$ echo $PWD
/home/lesmana
La variable FOO
no está definida y el directorio de trabajo no ha cambiado.
La salida del script muestra claramente que la variable fue establecida y el directorio fue cambiado. La comprobación posterior muestra que la variable no está establecida y el directorio no ha cambiado. ¿Qué ha pasado? Los cambios se hicieron en un nuevo shell. El shell actual generó un shell nuevo para ejecutar el script. El script se ejecuta en el nuevo shell y todos los cambios en el entorno tienen efecto en el nuevo shell. Una vez que el script ha terminado, el nuevo shell se destruye. Todos los cambios en el entorno en el nuevo shell se destruyen con el nuevo shell. Sólo el texto de salida se imprime en el shell actual.
Ahora sacamos el archivo:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Comprueba de nuevo el entorno:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
La variable FOO está activada y el directorio de trabajo ha cambiado.
El origen del script no crea un nuevo shell. Todos los comandos se ejecutan en el shell actual y los cambios en el entorno tienen efecto en el shell actual.
Tenga en cuenta que en este sencillo ejemplo el resultado de la ejecución es el mismo que el del abastecimiento del script. Esto no es necesariamente siempre el caso.
Considere el siguiente script pid.sh
:
#!/bin/sh
echo $$
(la variable especial $$
se expande al PID del proceso del shell que se está ejecutando)
Primero imprime el PID del shell actual:
$ echo $$
25009
Source the script:
$ source pid.sh
25009
Ejecuta el script, observa el PID:
$ ./pid.sh
25011
Origina de nuevo:
$ source pid.sh
25009
Ejecuta de nuevo:
$ ./pid.sh
25013
Puedes ver que al originar el script se ejecuta en el mismo proceso mientras que al ejecutarlo se crea un nuevo proceso cada vez. Ese nuevo proceso es el nuevo shell que se creó para la ejecución del script. El origen del script no crea un nuevo shell y por lo tanto el PID sigue siendo el mismo.
Tanto el abastecimiento como la ejecución del script ejecutarán los comandos en el script línea por línea, como si usted escribiera esos comandos a mano línea por línea.
Las diferencias son:
Use source si quiere que el script cambie el entorno en su shell actual. use execute en caso contrario.
Ver también:
La ejecución de un script lo ejecuta en un proceso hijo separado, es decir, se invoca una instancia separada del shell para procesar el script. Esto significa que cualquier variable de entorno, etc., definida en el script no puede ser actualizada en el shell padre (actual).
El uso de un script significa que es analizado y ejecutado por el propio shell actual. Es como si escribiera el contenido del script. Por esta razón, no es necesario que el script que se está abasteciendo sea ejecutable. Pero tiene que ser ejecutable si lo estás ejecutando, por supuesto.
Si tienes argumentos posicionales en el shell actual, no se modifican.
Así que si tengo un archivo a.sh
que contiene:
echo a $*
y hago
$ set `date`
$ source ./a.sh
obtengo algo como:
a Fri Dec 11 07:34:17 PST 2009
Mientras que:
$ set `date`
$ ./a.sh
me da:
a
Espero que eso ayude.
La ejecución es esencialmente lo mismo que teclear cada línea del script en el prompt de comandos una a una…
La ejecución inicia un nuevo proceso y luego ejecuta cada línea del script, sólo modificando el entorno actual por lo que devuelve.
Si se ejecuta, se obtienen todas las variables extra definidas en el script.
Así que si tienes configuraciones o definiciones de funciones debes hacer source y no ejecutar. Las ejecuciones son independientes del entorno de los padres.
El comando source
ejecuta el script proporcionado (el permiso de ejecución no es obligatorio ) en el entorno del shell actual, mientras que ./
ejecuta el script ejecutable proporcionado en un nuevo shell.
Además, compruebe esta respuesta como ejemplo: https://superuser.com/a/894748/432100