¿Cuál es la diferencia entre usar `sh` y` source`?

¿Cuál es la diferencia entre sh y source ?

 source: source filename [arguments] Read and execute commands from FILENAME and return. The pathnames in $PATH are used to find the directory containing FILENAME. If any ARGUMENTS are supplied, they become the positional parameters when FILENAME is executed. 

Y para man sh :

 NAME bash - GNU Bourne-Again SHell SYNOPSIS bash [options] [file] COPYRIGHT Bash is Copyright (C) 1989-2004 by the Free Software Foundation, Inc. DESCRIPTION Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file. Bash also incorporates useful features from the Korn and C shells (ksh and csh). Bash is intended to be a conformant implementation of the IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2). 

Cuando llama al source (o su alias), inserta el script en el proceso bash actual . Entonces puedes leer las variables establecidas por el script.

Cuando llamas a sh , inicias un fork (subproceso) que ejecuta una nueva sesión de /bin/sh , que generalmente es un enlace simbólico para bash . En este caso, las variables de entorno establecidas por el subguión se eliminarán cuando finalice el subguión.

Precaución : sh podría ser un enlace simbólico a otro shell.

Una pequeña muestra

Por ejemplo, si desea cambiar el directorio de trabajo actual de una manera específica, no podría hacer

 cat < myCd2Doc.sh #!/bin/sh cd /usr/share/doc eof chmod +x myCd2Doc.sh 

Esto no hará lo que esperas:

 cd /tmp pwd /tmp ~/myCd2Doc.sh pwd /tmp 

porque el directorio de trabajo actual es parte del entorno y myCd2Doc.sh se ejecutará en una subcadena .

Pero:

 cat >myCd2Doc.source <  

(Escribí una pequeña muestra de la función mycd ).

Nivel de ejecución $SHLVL

 cd /tmp printf %b '\43\41/bin/bash\necho This is level \44SHLVL.\n' >qlvl.sh bash qlvl.sh This is level 2. source qlvl.sh This is level 1. 

Poca recursión

 cat < qlvl.sh #!/bin/bash export startLevel echo This is level $SHLVL starded:${startLevel:=$SHLVL}. ((SHLVL<5)) && ./qlvl.sh eoqlvl chmod +x qlvl.sh ./qlvl.sh This is level 2 starded:2. This is level 3 starded:2. This is level 4 starded:2. This is level 5 starded:2. source qlvl.sh This is level 1 starded:1. This is level 2 starded:1. This is level 3 starded:1. This is level 4 starded:1. This is level 5 starded:1. 

Y una prueba final :

 printf %b '\43\41/bin/bash\necho Ending this.\nexit 0\n' >finalTest.sh bash finalTest.sh Ending this. source finalTest.sh Ending this. 

... Puede notar un comportamiento diferente entre ambas syntax. 😉

La principal diferencia es que se ejecutan en un proceso diferente.

Entonces, si source un archivo foo que hace un cd , el shell de sourcing (por ejemplo, tu caparazón interactivo en el terminal) se ve afectado (y su directorio actual cambiará)

Si ejecuta sh foo el cd no afecta el shell de origen, solo el proceso sh recién creado se ejecuta foo

Lea la guía avanzada de scripts de Bash .

Esa diferencia no es específica de Linux; cada implementación de Posix lo tendría.

Como han mencionado otros, cuando ejecuta sh test.sh , cualquier cambio que test.sh realice en su entorno de shell no persistirá una vez que el proceso haya finalizado.

Sin embargo, también tenga en cuenta que cualquier elemento de su entorno que no se exporte (p. Ej., Variables, alias y funciones de shell) no estará disponible para el código en test.sh cuando se ejecute como un subproceso (es decir, con una sh test.sh ).

Por ejemplo:

 $ cat > test.sh echo $foo $ foo=bar $ sh test.sh $ . test.sh bar 

Ejemplo 2:

 lap@my-ThinkPad:~$ cat test.sh #!/bin/sh cd /etc lap@my-ThinkPad:~$ sh test.sh lap@my-ThinkPad:~$ pwd /home/savoury lap@my-ThinkPad:~$ source test.sh lap@my-ThinkPad:/etc$ pwd /etc lap@my-ThinkPad:/etc$ 

Cuando ejecutas un progtwig con el comando sh:

  • su terminal usará sh o Bourne Shell para ejecutar el progtwig.
  • se crea un nuevo proceso porque Bash hace una copia exacta de sí mismo. este proceso hijo tiene el mismo entorno que su padre, solo el número de identificación del proceso es diferente. (este proceso llamado bifurcación)
  • necesita tener permiso de ejecución para ejecutarlo (ya que está bifurcando)

y cuando usas el comando fuente:

  • ejecuta el progtwig con su intérprete predeterminado
  • usted ejecuta el proceso en su terminal actual (técnicamente su comando * nix es interpretado)
  • Dado que el progtwig se ejecutará en la terminal actual, no es necesario que le des permisos de ejecución