¿Cuál es la diferencia entre ejecutar "bash script.sh" y "./script.sh"?

42

Si script.sh es solo algo típico como

#!/bin/bash
echo "Hello World!"

¿Hay alguna forma preferida de ejecutar el script? Creo que primero tienes que modificarlo para que se vuelva ejecutable.

usuario72136
fuente

Respuestas:

56

Para su secuencia de comandos específica, de cualquier manera funcionará, excepto que ./script.shrequiere ejecución y bits legibles, mientras que bash script.shsolo requiere bits legibles.


La razón de la diferencia de requisitos de permisos radica en cómo se carga el programa que interpreta su script:

  • ./script.sh hace que su shell ejecute el archivo como si fuera un ejecutable normal.

El shell se bifurca y usa una llamada al sistema (por ejemplo execve) para hacer que el sistema operativo ejecute el archivo en el proceso bifurcado. El sistema operativo verificará los permisos del archivo (por lo tanto, se debe establecer el bit de ejecución) y reenviará la solicitud al cargador del programa , que observa el archivo y determina cómo ejecutarlo. En Linux, los ejecutables compilados comienzan con un número mágico ELF , mientras que los scripts comienzan con un #!( hashbang ). Un encabezado hashbang significa que el archivo es un script y debe ser interpretado por el programa que se especifica después del hashbang. Esto permite que un script mismo le diga al sistema cómo interpretar el script.

Con su script, el cargador del programa se ejecutará /bin/bashy pasará ./script.sh como argumento de línea de comando.

  • bash script.shhace que su shell se ejecute bashy pase script.shcomo argumento de línea de comandos

Entonces, el sistema operativo se cargará bash(sin siquiera mirarlo script.sh, porque es solo un argumento de línea de comandos). El bashproceso creado entonces interpretará el script.shporque se pasa como el argumento de la línea de comandos. Como script.shsolo se lee bashcomo un archivo normal, no se requiere el bit de ejecución.


Sin ./script.shembargo, recomiendo usar , porque es posible que no sepa qué intérprete requiere el script. Deje que el cargador de programas determine eso por usted.

SkyDan
fuente
3
Si el bit ejecutable no está configurado, también puede ejecutar el script haciendo ". ./Script.sh"
Dog eat cat world
1
@ Perro Tienes razón. El punto es un acceso directo para el comando incorporado 'fuente', que ejecuta el script en el proceso bash actual. Entonces solo se requiere el bit legible.
SkyDan
55
@Dogeatcatworld si bien eso es cierto, correr . ./script.shno es lo mismo que bash script.sh(o ./script.sh. Considere el script #!/usr/bin/python -V<newline> print test.
casey
12
Tenga en cuenta que el aprovisionamiento de un script puede contaminar la sesión interactiva. Por ejemplo, si un script cambia la variable de entorno PATH, este cambio afectará a los comandos que se ejecutan después de la fuente. Este enfoque realmente debería reservarse para situaciones en las que dependa de los efectos secundarios (secuencias de comandos de configuración del entorno y similares). Para otras situaciones en las que no puede cambiar los permisos, el método más seguro es ejecutar el comando en la línea shebang, seguido del nombre del script.
ctt
66
Tenga en cuenta que, si obtiene un script en el directorio actual, no necesita usar ./ ; acaba de decir . script.sh. Pero estoy de acuerdo con las personas que desalientan el uso del .comando en scripts que no están destinados a ser invocados de esa manera. Me sorprende que nadie mencione eso, si el script contiene exitcomandos, y lo obtiene, podría cerrar la sesión. Un problema menos grave sería si el script hace un cd, ya que eso también afectaría el shell primario (interactivo).
Scott
18

bash script.shinvoca el script directamente usando bash.
./script.shestá usando el shebang #!/bin/bashpara determinar cómo ejecutar.

Si realmente quiere saber, qué binario se ejecuta si lo hace bash script.sh, puede averiguarlo which bash.

Entonces, en su ejemplo, no hay diferencia. Sí, chmod +x script.shdebe poder ejecutarlo directamente a través de ./script.sh.

xx4h
fuente
2
Bueno, no hace ninguna diferencia, suponiendo que /bin/bashsea ​​el primero bashen tu $PATH.
cjm
Tienes razón. Y el shebang #!/bin/bashsolo funciona si hay un/bin/bash
xx4h
Bash (versión 4.2.37) en mi sistema ejecuta scripts incluso sin el bit de ejecución establecido. ¿Por qué dices que se requiere un bit de ejecución?
SkyDan
Sí, el bit de ejecución solo es necesario invocando vía ./script.sh.
xx4h
4

Cree un archivo Delete_Self.sh como este:

 #!/bin/rm

 echo I am still here!

Ejecute este script ya sh Delete_Self.shque verá "¡Todavía estoy aquí!" repitió.

Conviértalo en ejecutable y ejecútelo, ya ./Delete_Self.shque verá que nada se repite, mientras que el archivo en Delete_Self.shsí no está.

Entonces la diferencia es que:

  • bash script.shignorará el #! línea, porque bash se especifica como el programa para ejecutar script.sh.
  • ./script.shleerá el #! línea para determinar el programa a ejecutar script.sh.
David
fuente
+1 para el buen ejemplo
ThisaruG
1

Además de las otras respuestas, es útil conocer la diferencia entre ejecutar un script a través de ./script.sh(i) y la fuente ./script.sh(ii): la versión (i) crea un nuevo shell para ejecutar el comando, mientras que (ii) lo ejecuta en el shell actual: que puede ser obligatorio si el ejecutable cambia las variables de entorno que deben conservarse después de que el ejecutable salga. Por ejemplo, para activar un entorno python conda se debe usar lo siguiente:

source activate my_env

NB Otra alternativa a la sourceque puede encontrar es el .incorporado, es decir

. activate my_env
einonm
fuente