Cuál es la diferencia entre ejecutar un script bash usando sh y ./

Esta misma pregunta puede surgir al utilizar cualquier tipo de script, no sólo los de bash. ¿Hay alguna diferencia importante entre ejecutar un script a través del intérprete y ejecutarlo directamente?

Un misterio más que develaremos en este interesante post de Usemos Linux (uL).


Cuando ejecutás un script pasando el nombre de archivo del script a un intérprete (sh, python, perl, etc.), en realidad estás ejecutando el intérprete pasándole como argumento el programa que querés ejecutar. Por ejemplo, ejecutamos el intérprete sh pasándole el argumento miscript.sh.

sh miscript.sh

Si ejecutás el script por sí solo, el sistema va a llamar al intérprete que necesite y, luego sí, ejecutará el script pasándolo como argumento al intérprete, pero todo en forma automática y sin que el usuario que ejecutó el script se entere.

./miscript.sh

Para poder ejecutar un script por sí solo deben cumplirse 2 condiciones:

1) el script debe incluir un “bang line”. Se trata de la primera línea de un script, que debe comenzar con los caracteres #! y que debe especificar la ruta en la que se encuentra el intérprete. Es importante notar que esta condición se cumple para cualquier tipo de script (python, perl, etc.), no sólo los de bash.

Así, por ejemplo, nuestro script debería contener como primera línea lo siguiente:

#!/bin/bash

2) el archivo debe tener permisos de ejecución:

Para otorgar permisos de ejecución a nuestro script, debemos escribir:

chmod a+x miscript.sh

Listo, ahora sólo basta con ejecutarlo así:

./miscript.sh

O copiando el script a una ruta “especial” que permita invocarlo fácilmente. Por ejemplo, podemos copiarlo en /usr/sbin y ejecutarlo desde cualquier parte sin incluir la ruta completa donde se encuentre:

Copiamos:

sudo cp miscript.sh /usr/sbin/miscript

Ejecutamos:

miscript

Como ves, en realidad lo que ocurre detrás de escena es muy similar en ambos casos. Sin embargo, al incluir una “bang line”, tus scripts serán mucho más fáciles de distribuir, ya que los usuarios no deberán recordar la ruta en la que se encuentran los intérpretes necesarios para poder ejecutarlos. Conclusión: es básicamente una cuestión de comodidad.


19 comentarios

  1.   el_que_sabe@gmail.com dijo

    Bash es un programa informático cuya función consiste en interpretar órdenes.

    Está basado en la shell de Unix y es compatible con POSIX.

    en cambio la sh es un programa informático cuya función consiste en interpretar órdenes.
    Incorpora características tales como control de procesos, redirección
    de entrada/salida, listado y lectura de ficheros, protección,
    comunicaciones y un lenguaje de órdenes para escribir programas por
    lotes o scripts. Fue el intérprete usado en las primeras versiones de Unix y se convirtió en un estándar de facto.

  2.   Diana C dijo

    Hola soy principiante en el uso de scripts y quisiera saber si alguien me puede ayudar con un problema que tengo:

    Estoy manejando un programa que requiere de la inclusión de varios datos iniciales mediante la consola y me entere que por medio de un script es posible ejecutar el programa con los datos iniciales, para no tener que escribirlos una y otra vez cuando necesite ejecutar el programa.

    No se como hacerlo, así que si alguien puede ayudarme con esto le estaré muy agradecida.

  3.   Usemos Linux dijo

    Mirá, depende en qué lenguaje de programación estés escribiendo el script. No obstante, en cualquier caso lo que precisás es:

    1) Si querés que el usuario tenga que ingresar esos datos siempre que se ejecute el script, el procedimiento más común es que una variable tome los valores ingresados en el input.

    2) En caso de que los valores sean siempre los mismos, podés utilizar constantes.

    3) Otra opción es la posibilidad de que tu script pueda tomar parámetros.

    Saludos! Pablo.

  4.   Usemos Linux dijo

    Es interesante lo que mencionás. Se llama de las 2 formas: shebang line o directamente bang line. Te paso el dato: http://python.about.com/od/programmingglossary/g/defbangline.htm
    Saludos! Pablo.

  5.   @llomellamomario dijo

    Interesante, nunca me habia parado a pensar en ese detalle. Estaria interesante ver mas articulos de retoque consolero, entre ellos la famosa recompilacion de kernel para quitar los kilos de cofigo innecesario que solo estan ahi por compatibilidad y mejorar la velocidad del sistema.

  6.   Usemos Linux dijo

    OK. Lo voy a tener en cuenta.
    Saludos! Pablo.

  7.   Usemos Linux dijo

    Me alegro que haya servido. Siempre intento publicar cosas que me parece que pueden resultar interesantes y prácticas.
    Un fuerte abrazo! Pablo.

  8. Todo programador con buenas costumbres añade un “bang line” en la primera línea de código. En Python nunca olvido la codificación y el bang line.
    #!/usr/bin/python2.7
    #*.*encoding=utf-8*.*

  9.   Diex02 dijo

    Excelente, ojalá puedan estar publicando mas información sobre la linea de comandos, sobre todo cuando se trata de compilar o instalar desde archivos fuentes (tar.gz, etc.)

  10.   joe di castro dijo

    Jamás había oído lo de “bang line” siempre lo he conocido como Shebang

    http://en.wikipedia.org/wiki/Shebang_%28Unix%29

    Saludos

  11. interesante nota… gracias!

  12.   eM Di eM dijo

    que interesante, me declaro ignorante total en programacion y en todo lo relacionado con script, no tenia idea del funcionamiento, pero si he notado que algunos tienen ese encabezado.

  13.   Mario Raimondi dijo

    Una aclaración que me pasó que tiene que ver con esta entrada: quise instalar un gadget de adobe air (una calculadora de probabilidades de poker). Lo que hace el instalador de adobe air es ejecutar el script corespondiento con “su” pero de la forma ./ pidiéndote la contraseña de root. Como el script no tenía permisos de ejecución te tiraba permiso denegado, la solución: ejecutar el script con sh si no querés cambiar los permisos (mas rapido bah que ir a la carpeta tmp chmod y todo eso) . Ahi se ejecuta el script llama al instalador de adobe y a otra cosa mariposa.

  14.   Ero-Sennin dijo

    Artículo interesantísimo! Gracias por ayudarme a saber un poquico más de la consola. A ver si sigues publicando artículos como estos ^^.
    Sigue así, que este es sin duda mi blog favorito!!

  15.   Erpower dijo

    Hay que tener en cuenta que puede haber diferencias entre las versiones del intérprete que se usen. Ejecutando el script directamente según el shebang no hay forma de indicar qué versión del intérprete utilizar, lo que puede ser necesario. Si en su lugar ejecutas el intérprete y pasas como parámetro el script, sabes qué versión del mismo se está ejecutando.

    Por ejemplo en Python, si el shebang es #!/usr/bin/python2.4 el programa se ejecutará de forma diferente a si es #!/usr/bin/python2.6 o si es #!/usr/bin/python (que, normalmente, es un enlace simbólico a la versión de Python que se tenga instalada y configurada por omisión). Esto ocurre porque Python 2.6 tiene nueva funcionalidad que no existía en Python 2.4, así que escribir un script que use esa funcionalidad indicando un shebang #!/usr/bin/python fallará si el sistema tiene sólo instalado python 2.4. En cambio, puedes forzar siempre que el script se ejecute con la versión de python que quieras si lo arrancas con “python2.4 /ruta/al/script.py” o “python2.6 /ruta/al/script.py”/

    Para shell scripts, también hay diferencias entre los shell que uses, así que usar #!/bin/sh y #!/bin/bash puede tener distintos resultados según el script. Si escribes un script usando características que existen sólo en bash pero indicas un shebang #!/bin/sh, probablemente tu script funcione en Linux (en la mayor parte de distribuciones /bin/sh es un enlace simbólico a bash) pero seguramente falle en otros UNIX en los que bash no esté instalado o en los que /bin/sh no sea un enlace simbólico a /bin/bash.

    También relacionado con la portabilidad, hay que tener en cuenta que la ruta indicada en el shebang es absoluta, y hay veces que los intérpretes están instalados en otros lugares. Por ejemplo, es común tener el intérprete de python instalado en /usr/local/bin/python si has bajado y compilado Python en lugar de usar un paquete de tu distribución. Si tu shebang es #!/usr/bin/python, el script no funcionará en esos sistemas. Para intentar evitar estos problemas, puedes usar como shebang “#!/usr/bin/env python” (o “#!/usr/bin/env sh”) como se explica en http://en.wikipedia.org/wiki/Shebang_(Unix)#Portability

  16. Coincido contigo Erpower, tanto la version del interprete como la ruta del mismo son variables y no constantes, mas aun si se considera que las distriobuciones GNU/Linux no son las unicas que utilizan Bash (tambien están: freeBSD, OpenSolaris, Mac) y muchas de ellas tiene configuraciones o rutas distintas.

    Lo importante, es conocer que se tiene la flexibilidad (como bien lo comentaste) de jugar con el llamado al script, ya sea con ./ o con sh (o python… etc)

  17.   Usemos Linux dijo

    Gracias Jonathan! Qué bueno verte comentar!
    Saludos! Pablo.

  18.   antonio dijo

    En ningun lado sale lo que quiero saber, o por lo menos no se como plantearlo en el buscador, yo quiero crear un script que por un motivo xX ejecute el comando aptitude o “su” (solo es un ejemplo pero son los 2 casos que se me ocurren) y en el caso de aptitude a veces me pide introducir “y o n” o en el “su” me pide la clave… quisiera que el script seleccionara esas opciones automaticamente ya sea pasando un parametro o utilizando algun metodo que no conozca…. muchas gracias por la atencion

    1.    usemoslinux dijo

      Hola antonio! Si tu problema es tener que ingresar la clave, no creo que haya alguna solución. Precisamente, porque se trata de una medida de seguridad, para que no cualquier pueda instalar un programa.
      Respecto de aptitude y tener que poner y o yes, yo creo que sí se puede solucionar. No recuerdo en este momento el parámetro exacto a utilizar, pero basta con averiguar en los man pages. Abrí un terminal e ingresá el comando: man aptitude.
      Abrazo! Pablo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

  1. Responsable de los datos: Miguel Ángel Gatón
  2. Finalidad de los datos: Controlar el SPAM, gestión de comentarios.
  3. Legitimación: Tu consentimiento
  4. Comunicación de los datos: No se comunicarán los datos a terceros salvo por obligación legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu información.