2009-12-11 15:24:17 +0000 2009-12-11 15:24:17 +0000
302
302

¿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

Respuestas (6)

369
369
369
2010-08-16 21:58:48 +0000

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.

Terminología

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.

Demostración

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.

Otra demostración

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.

Resumen

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:

  • Cuando se ejecuta el script se abre un nuevo shell, se escriben los comandos en el nuevo shell, se copia la salida en el shell actual, y se cierra el nuevo shell. Cualquier cambio en el entorno tendrá efecto sólo en el nuevo shell y se perderá una vez que se cierre el nuevo shell.
  • Cuando usted source el script está escribiendo los comandos en su shell actual. Cualquier cambio en el entorno tendrá efecto y se mantendrá en su shell actual.

Use source si quiere que el script cambie el entorno en su shell actual. use execute en caso contrario.

  • *

Ver también:

23
23
23
2009-12-11 15:35:56 +0000

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.

9
9
9
2009-12-11 15:27:08 +0000

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.

6
6
6
2012-02-23 07:27:43 +0000

Además de lo anterior, ejecutar el script como ./myscript requiere permiso de ejecución para el archivo myscript mientras que el sourcing no requiere ningún permiso de ejecución. Por eso no se requiere chmod +x myscript antes de source myscript

5
5
5
2009-12-11 15:25:38 +0000

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.

2
2
2
2015-03-27 14:04:20 +0000

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