¿Cuál es la diferencia entre ./ y sh para ejecutar un script?

65

He escrito un guión simple. Cuando ejecuto sh <myscriptname.sh> , obtuve el resultado correcto, pero cuando ejecuto ./<myscriptname.sh> , recibí un error.

¿Cuál es la diferencia entre cuando hago sh y ./ ?

    
pregunta mr_eclair 23.01.2011 - 16:16

6 respuestas

62

Cuando ejecuta cualquier secuencia de comandos pasando el nombre de archivo al programa de intérprete de secuencia de comandos, está ejecutando el programa de interpretación con la secuencia de comandos como un argumento pasado a la misma. Por ejemplo, esto se vería como el proceso 'sh' con el argumento 'filename.sh'. El intérprete sh está abriendo el archivo.

Por otro lado, si ejecuta el script en sí, el sistema llama al programa de intérprete especificado y lo ingresa en el contenido de los scripts. En este caso, el proceso se ve como 'filename.sh' sin argumentos.

Deberías asegurarte de tener una línea explosiva:

#!/bin/bash
# bash script here

Una línea bang es la primera línea en el script y comienza con los mismos dos caracteres #! , esto es lo que el sistema lee cuando intenta ejecutar el script y luego el sistema pasa el guión del programa inmediatamente después. Tenga en cuenta que esta línea no tiene nada que ver con bash y funciona igual de bien para python y perl, a pesar de que son idiomas muy diferentes. Utilizaría #!/usr/bin/python por ejemplo y luego lo seguiría con el código python.

Una vez que tenga su script, asegúrese de haber establecido los permisos de ejecución:

chmod a+x filename.sh

Luego puede ejecutar el script como su propio proceso:

./filename.sh

O coloque el archivo en una ubicación conocida con un buen nombre de programa, como /usr/sbin y ejecute desde cualquier lugar:

sudo cp filename.sh /usr/sbin/program-name
program-name

Y este es realmente el beneficio práctico de usar la línea bang con los permisos correctos: se trata de implementación . Es muy difícil lograr que los usuarios ejecuten un script si tienen que recordar con qué programa ejecutar el script. Recuerde dar una ruta completa al script cada vez que quiera ejecutarlo. Donde ponerlo en /usr/local/bin por ejemplo, y hacerlo ejecutable, puede ahorrar una gran cantidad de dolor para las personas que intentan usar su script. Estos programas estarán disponibles para todos usuarios en su computadora.

También es bueno para la identificación. Si ingresa al programa top , un script ejecutado sin la línea bang simplemente tendrá el nombre del intérprete, es decir, bash , perl o python . Pero si se ejecuta una secuencia de comandos con los permisos adecuados, se muestra el nombre de la secuencia de comandos.

Nota: si desea distribuir un script que sea accesible para todos, cree una página man y un paquete Deb para instalarlo. Necesitamos reducir el número de scripts aleatorios en línea y aumentar la cantidad de debuts que se pueden desinstalar.

    
respondido por el Martin Owens -doctormo- 23.01.2011 - 16:31
37

La versión corta:

  • sh es el intérprete de línea de comandos (guión).
    La ejecución de sh my_script hace que dash interprete el guión.

  • ./ intenta averiguar qué intérprete usar, mirando la primera línea. P.ej. #!/bin/bash , o incluso #!/bin/ruby (como oppsed to running ruby my_script ).

respondido por el Stefano Palazzo 23.01.2011 - 16:44
3

La diferencia que haces es,

  • con sh , está ejecutando un programa que interpretará las líneas en su secuencia de comandos del mismo modo que las habría escrito en el indicador interactivo de la terminal,

  • con ./ está haciendo un atajo suponiendo que el script está justo aquí en el directorio actual en el que está sentado Y será ejecutable (porque, por ejemplo, emitió chmod +x myscript.sh ), guardando un tiempo invaluable para los tiempos futuros: -)

respondido por el meduz 23.01.2011 - 23:13
3

Hay tres razones principales por las que podría estar recibiendo un error:

  • el archivo no es ejecutable
    Ejecute chmod +x <myscriptname.sh> para corregir eso
  • la partición no permite ejecutar secuencias de comandos (está montado " noexec ")
    copiar el script a /usr/local/bin
  • la línea #! tiene un error
    asegúrese de que la primera línea sea #!/bin/sh o #!/bin/bash

Si su primera línea se ve bien, pero todavía no funciona, asegúrese de que el archivo no tenga terminaciones de línea DOS.

El error se vería así:

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

Puedes arreglarlo ejecutando dos2unix <myscriptname.sh> , o si no tienes eso,
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh> .

    
respondido por el Mikel 03.02.2011 - 23:03
0

Y la respuesta es que sh es el nombre para shell muy popular. Pero anticuado y reemplazado por otros. Hoy en día, sh está vinculado a otras conchas instaladas en la máquina. p.ej. Tengo bash putted allí. La ejecución de cualquier shell desde sh generalmente activa algún modo de 'compatibilidad' con el comportamiento original de 'shell'.

Entonces la solución es bastante simple. Mire qué hay detrás del comando sh (ls -al / bin / sh), y ponga #! / Bin / whatever_you_find_there como primera línea (o si hay algo así en su script, edítelo).

Y, como alternativa, puede haber algún error en el script en sí. Como la dependencia que se cumple por sh, pero no el intérprete que realmente se usa.

    
respondido por el przemo_li 23.01.2011 - 18:09
0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

No /usr/sbin , eso es para herramientas administrativas no esenciales, /usr/local/bin es una mejor opción si no quieres tener un ~/bin/ , pero evitando sudo tanto como posible es aconsejable.

    
respondido por el Joey1978 24.01.2011 - 08:25

Lea otras preguntas en las etiquetas