Pregunta ¿Cuál es la diferencia entre ejecutar un script de Bash y obtenerlo?


¿Cuál es la diferencia entre ejecutar un script de Bash como A y obtener un script de Bash como B?

A
> ./myscript

B
> source myscript

213


origen




Respuestas:


Respuesta corta: el abastecimiento ejecutará los comandos en el proceso de shell actual. la ejecución ejecutará los comandos en un nuevo proceso de shell. ¿sigo confundido? entonces por favor continúa leyendo la respuesta larga.

Terminología:

Para aclarar alguna confusión común sobre la sintaxis a ejecutar y la sintaxis a la fuente:

./myscript

Ejecutar  myscript siempre que el archivo sea ejecutable y esté ubicado en el directorio actual. La barra diagonal líder (./) denota el directorio actual. Esto es necesario porque el directorio actual generalmente no está en $PATH.

myscript

Ejecutar  myscript si el archivo es ejecutable y se encuentra en algún directorio en $PATH.

source myscript

Fuente  myscript. el archivo no necesita ser 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

Fuente  myscript. Esta sintaxis es definido por POSIX. Bash definido source como un alias al comando de punto.

Demostración:

Considerar 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, verificamos el entorno actual:

$ env | grep FOO
$ echo $PWD
/home/lesmana

La variable FOO no está definido y estamos en el directorio de inicio.

Ahora nosotros ejecutar el archivo:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Comprueba el medioambiente de nuevo:

$ env | grep FOO
$ echo $PWD
/home/lesmana

La variable FOO no está configurado y el directorio de trabajo no cambió.

El resultado del script muestra claramente que la variable se configuró y el directorio se modificó. El control posterior muestra que la variable no está configurada y el directorio no ha cambiado. ¿Que pasó? Los cambios fueron hechos en nuevo cáscara. los corriente shell engendró un nuevo shell para ejecutar el script. El script se ejecuta en el nuevo shell y todos los cambios en el entorno surten efecto en el nuevo shell. Después de que la secuencia de comandos termina, se destruye el nuevo caparazón. Todos los cambios en el entorno en el nuevo shell se destruyen con el nuevo shell. Solo el texto de salida se imprime en el shell actual.

Ahora nosotros fuente el archivo:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Comprueba el medioambiente de nuevo:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

La variable FOO está configurada y el directorio de trabajo ha cambiado.

La fuente del script no crea un nuevo shell. Todos los comandos se ejecutan en el shell actual y los cambios en el entorno surten efecto en el shell actual.

Tenga en cuenta que en este ejemplo simple, el resultado de la ejecución es el mismo que el de obtener el script. Esto no es necesariamente siempre el caso.

Otra demostración:

Considera seguir guión pid.sh:

#!/bin/sh
echo $$

(la variable especial $$ se expande al PID del proceso de shell en ejecución actual)

Primero imprima el PID del shell actual:

$ echo $$
25009

Fuente el guion:

$ source pid.sh
25009

Ejecute el script, tenga en cuenta el PID:

$ ./pid.sh
25011

Fuente de nuevo:

$ source pid.sh
25009

Ejecutar nuevamente:

$ ./pid.sh
25013

Puede ver que el origen del script se ejecuta en el mismo proceso mientras que la ejecución del script crea un nuevo proceso cada vez. Ese nuevo proceso es el nuevo shell que se creó para la ejecución del script. La fuente del script no crea un nuevo shell y, por lo tanto, el PID se mantiene igual.

Resumen

Tanto el abastecimiento como la ejecución del guión ejecutarán los comandos en el guión línea por línea, como si hubiera escrito esos comandos a mano línea por línea.

Las diferencias son:

  • Cuando tú ejecutar el script que estás abriendo nuevo shell, escriba los comandos en el nuevo shell, copie el resultado a su shell actual, luego cierre el nuevo shell. Cualquier cambio en el entorno tendrá efecto solo en el nuevo shell y se perderá una vez que se cierre el nuevo shell.
  • Cuando tú fuente la secuencia de comandos que está escribiendo los comandos en su corriente cáscara. Cualquier cambio en el entorno tendrá efecto y permanecerá en su caparazón actual.

Utilice la fuente si desea que la secuencia de comandos cambie el entorno en su caparazón actualmente en ejecución. use ejecutar lo contrario.


Ver también:


277



Un uso de sourcing es crear una forma rudimentaria de archivo de configuración para sus scripts. Empiezas estableciendo varias variables a los valores predeterminados, y luego fuente en algo como myscript.conf, y ese script de origen puede tener instrucciones de asignación que anulan los valores que desees. Como el script de origen no comienza con # / bin / bash, no se recomienda ejecutarlo directamente. - LawrenceC
Así que la fuente es algo así como ejecutarlo en un ámbito global, y la ejecución crea un nuevo alcance local. ¿Se puede extender esto a una función en un script? para ejecutar una función (normalmente) o para "fuente"? - aliteralmind
Llamar a una función de shell normalmente se comporta de manera muy parecida a la fuente. Llamar a una función de shell dentro de una subshell se comporta de forma similar a la ejecución. - lesmana
¿Hay alguna diferencia entre usar source myscript.sh y . myscript.sh? - Holloway
prácticamente no hay diferencia si usas bash. la fuente es un alias para puntear en bash. - lesmana


Al ejecutar una secuencia de comandos, se ejecuta en un proceso secundario independiente, es decir, se invoca una instancia de shell separada para procesar la secuencia de comandos. Esto significa que cualquier variable de entorno, etc., se define en el script hipocresía ser actualizado en el shell principal (actual).

La fuente de un script significa que es analizado y ejecutado por el propio shell actual. Es como si hubiera tipeado el contenido del guión. Por esta razón, el script que se obtiene no necesita ser ejecutable. Pero tiene que ser ejecutable si lo estás ejecutando, por supuesto.

Si tiene argumentos posicionales en el shell actual, no se modifican.

Entonces si tengo un archivo a.sh que contiene:

echo a $*

y yo hago

$ set `date`
$ source ./a.sh

Obtengo algo como:

a Fri Dec 11 07:34:17 PST 2009

Mientras:

$ set `date`
$ ./a.sh

me da:

a

Espero que ayude.


21



aunque esta respuesta es correcta en todos los sentidos, me resulta muy difícil de entender porque se demuestra utilizando otro concepto (configuración de parámetros posicionales), que es, en mi opinión, aún más confuso que la diferencia de aprovisionamiento y ejecución. - lesmana


El abastecimiento es esencialmente lo mismo que escribir cada línea de la secuencia de comandos en el indicador de comando de uno en uno ...

La ejecución inicia un nuevo proceso y luego ejecuta cada línea del script, solo modificando el entorno actual por lo que devuelve.


5





Sourcing obtiene todas las variables adicionales definidas en el script.
Entonces, si tiene configuraciones o definiciones de funciones, debe buscar y no ejecutar. Las ejecuciones son independientes del entorno de los padres.


4





Además de lo anterior, ejecutando el script como ./myscript requiere permiso de ejecución para el archivo myscript mientras que el abastecimiento no requiere ningún permiso de ejecución. Es por eso que chmod +x myscript no es requerido antes source myscript


4



Es cierto, pero si eso es un problema, siempre puede ejecutar bash myscript. - Daniel Beck♦


Si recuerdo correctamente, ejecutar el script ejecuta el ejecutable en #! alinearse con el archivo de script como argumento (por lo general, iniciar un nuevo shell y buscar el script de manera efectiva en el nuevo shell, como con #!/bin/sh);
mientras que el origen del script ejecuta cada línea en su entorno de shell actual, lo que es útil para mutar el shell actual (por ejemplo, proporcionar una forma de definir funciones de shell y exportar variables de entorno).


3





source comando ejecuta la secuencia de comandos proporcionada (el permiso ejecutable es no es obligatorio) en el corriente entorno de shell, mientras ./ ejecuta el proporcionado ejecutable script en una nuevo cáscara.

Además, verifique esta respuesta, por ejemplo: https://superuser.com/a/894748/432100


2