./ vs. para ejecutar programas bajo terminal

13

Necesitaría algunas aclaraciones sobre la forma en que ejecutamos los ejecutables en la terminal. Esta podría ser una pregunta poco convincente, pero ¿cuál es la diferencia entre ejecutar un ejecutable con ./an_executabley . an_executable(supongamos que estamos en el directorio donde se encuentra an_executable)

Ya sé que el primero hace que el shell busque un_executable en el directorio actual ( .), pero ¿por qué no es /necesario después de .usar la última versión?

Gracias por adelantado.

zipzap
fuente
Ver también askubuntu.com/q/182012/26972
ysap

Respuestas:

22

La . executablesintaxis no funciona con cualquier ejecutable (¿o sí?). En cambio, es un alias para el bash sourceincorporado. Entonces, la diferencia es principalmente relevante para los scripts de bash, y la verdad es que son cosas completamente diferentes :)

./executablepide ejecutar el ejecutable "normalmente". ./es una referencia relativa a la ruta actual. Esto evita que el shell (bash) intente ubicar el ejecutable en un directorio $PATH(lo que haría si no especificara una ruta con el comando). La razón por la que no sólo puede hacer executablees una de la seguridad; imagine que descomprime un archivo que descargó y que contiene una versión maliciosa de ls. Si se ejecutara directamente desde su directorio actual, ejecutaría esa versión sin darse cuenta.

Por otro lado, . executableestá diciendo "fuente de un archivo llamado executable". Dado que está nombrando directamente el archivo y realmente no tiene que ser un ejecutable, la restricción de seguridad para $ PATH no se aplica. Sourcing solo "ejecutará" (o parece que se ejecuta) scripts de shell. Lo que hace es:

   source filename [arguments]
          Read and execute commands from filename  in  the  current  shell
          environment  and return the exit status of the last command exe‐
          cuted from filename.

Entonces ... ¿Cuál es realmente la diferencia entre la ejecución y el abastecimiento? Suponiendo que el mismo script de shell, ejecutarlo ( ./script) generará un nuevo shell, ejecutará el script dentro de ese shell, y cuando el script salga, cierre ese shell y regrese al shell principal. En efecto, comenzará un nuevo bashproceso para ejecutar el script).

( . script) hará que el shell actual lea los comandos del archivo como si se estuvieran escribiendo en la línea de comandos. No se genera un nuevo caparazón.

Una manera muy fácil de ver cómo se comporta esto es escribir un script que solo contenga exit. Si lo ./scripthace, parece que no sucederá nada, esto se debe a que se inicia un nuevo proceso de shell, el exitcomando sale de ese nuevo shell y su shell actual no se ve afectado.

Si usted . script, su terminal actual se cerrará, porque el exitcomando se ejecuta en el shell actual. Por lo tanto, es equivalente a escribir exiten el símbolo del sistema.

roadmr
fuente
De hecho, estaba lidiando con el script de shell cuando noté este comportamiento. Muchas gracias, esa es la respuesta que necesitaba. :)
zipzap
Otra pregunta planteada (si no le importa): si mi script contiene solo algunos mensajes simples con echo, y lo estoy ejecutando con ./script, entonces ¿por qué puedo ver los mensajes en el shell principal si el subshell se cierra? tan pronto como termina la ejecución?
zipzap
2
Porque mientras que el subshell es un proceso separado , utiliza el mismo terminal que el shell de invocación. Es similar a cómo todavía puede ver la lssalida: escribe el comando, se ejecuta, muestra la salida y luego termina, pero la salida permanece en el terminal.
roadmr
2
No confundas shell con terminal; Son cosas diferentes. Abra un terminal, y el símbolo del sistema lo proporciona un bashshell que se ejecuta dentro de él. Si escribe bash, ejecutará otro shell; para el primer shell, es solo un programa para ejecutarse. Si escribe exit, cerrará el último shell que inició, pero seguirá estando en el primer shell (el de cuando inició el terminal). Nuevamente, todo esto sucede dentro de la misma terminal.
roadmr
1
@DavidZ Lo mencioné :) "Sourcing solo" ejecutará "(o parece ejecutar) scripts de shell".
roadmr