¿Por qué necesito poner sh antes de ejecutar archivos .sh?


16

Cuando quiero ejecutar .sharchivos en la Terminal, tengo que ponerlos shdelante.

¿Hay alguna forma de evitar esto y, por lo tanto, guardar la escritura?


3
Hice una carpeta en ~ / bin para colocar mis scripts de shell y lo puse en mi $ PATH y también adjunté una Acción de carpeta a la carpeta ~ / bin para configurar automáticamente los permisos de ejecución porque es muy fácil de olvidar.
Kaydell

Respuestas:


22

Si está ejecutando su secuencia de comandos desde el shell, en realidad no necesita el #!/bin/shshebang como se describe en esta respuesta: todos los sistemas similares a Unix que he usado, incluido OS X, usarán de forma predeterminada /bin/shsi no se especifica específicamente un intérprete ( aunque es una buena idea, ya que los que no son shells no sabrán cómo ejecutar su script a menos que le den el shebang).

Tampoco necesitas una .shextensión. Usted hace necesario establecer los permisos de ejecución, por ejemplo,

$ chmod +x script.sh

(Este $es el indicador del shell; lo estoy usando para ilustrar los comandos que le da al shell interactivo. ¡No lo escriba!)

Sin embargo, creo que su confusión es que ha creado un script, por ejemplo script.sh, en el directorio actual, y está tratando de ejecutarlo simplemente escribiendo script.sh. p.ej

$ cat >script.sh
echo hello, world
^D
$ chmod +x script.sh
$ script.sh
-bash: script.sh: command not found

( ^Dsignifica control- D. Encontrarás esta notación en muchas reseñas sobre el uso de Unix).

El hecho de que script.shen este caso sea un script de shell es solo la mitad del problema; su problema real es que, por defecto, el shell no buscará un programa en el directorio actual. Sin embargo, esto funciona:

$ sh script.sh
hello, world

porque shestá tomando el guión como argumento.

Puede ejecutar un script, o, nuevamente, cualquier ejecutable, en el directorio actual, si está marcado como ejecutable (es decir chmod +x), especificando que desea ejecutar el que está en el directorio actual:

$ ./script.sh
hello, world

También puede mover el script a un directorio en su PATH. Recomiendo /usr/local/binpara esto si su script está destinado a ser utilizado en todo el sistema, o un bindirectorio en su hogar si el script es solo para usted. Este último requiere que agregue $HOME/bin, que se expande a su nuevo directorio bin, PATHagregando las siguientes líneas a su .profileen su directorio de inicio:

PATH=$HOME/bin:$PATH
export PATH

Finalmente, si lo desea, puede agregar el directorio actual a su PATH, lo que le permitirá ir a un directorio que contenga script.sh–o cualquier otro ejecutable– y escribir

$ script.sh

para ejecutarlo Sin embargo, no recomiendo esta práctica , ya que un atacante ahora puede engañarlo para que ejecute un ejecutable arbitrario soltando un script ejecutable (llamado, digamos, ls) en un directorio en el que estará. Sin embargo, si realmente quiere hacerlo, simplemente agregue lo siguiente a su .profile:

PATH=.:$PATH
export PATH

Pon el '.' al final del $ PATH en lugar del principio y ahora no necesita preocuparse por un fantasma 'ls'. (Aunque si alguien puede entrar en su sistema, tiene problemas más grandes.)
TJ Luoma

2
@TJ, pero usted no tiene que preocuparse por cosas como slo llso l... es decir, errores tipográficos. Solo déjalo .fuera $PATH. Además, no puede (o no debe) confiar necesariamente en todos los miembros de su sistema. Por ejemplo, suponga que hay algún exploit que le permite a un atacante colocar un archivo arbitrario en algún directorio, pero necesita que ejecute ese archivo para escalar a un exploit mejor (por ejemplo, recopilar datos y llamar a casa). ¡Defensa en profundidad!
Reid

@TJLuoma Lo que dijo @Reid, además tenga en cuenta que hay muchos casos de uso para un sistema Unix más allá de un escritorio personal OS X. No lo he probado, pero apuesto a que incluso la cuenta de invitado podría dejar uno de esos elementos en /tmpalgún otro directorio de escritura mundial.
zigg

Si está utilizando un sistema donde otras personas tienen acceso a los directorios que utiliza, tiene problemas más grandes.
TJ Luoma

@TJLuoma Es mejor que nunca uses múltiples cuentas en ningún sistema Unix. /tmpet al. ven con el territorio.
zigg

10

No necesita llamar shsi el archivo de script está marcado como ejecutable. En ese caso, puede llamarlo mi nombre como lo haría con cualquier otro comando del shell existente.


Para ser completamente apropiado, querrás hacer dos cosas:

  1. Edite su script para incluir una directiva shebang en la parte superior de su script:

    #!/bin/sh

    ... Eso le diría al intérprete qué intérprete usar para ejecutar el script; en este caso, el /bin/shejecutable.

  2. Marque el script como ejecutable por usted con el comando chmod :

    chmod u+x scriptname.sh

Una vez que haga ambas cosas, debería poder ejecutar su script escribiendo el nombre de archivo de su script en la línea de comando. Tendrá que estar en el mismo directorio que su script, a menos que también realice el paso agregado de agregar la carpeta que contiene a su variable PATH . Si no le importa qué shell ejecuta el script, no necesita el paso uno para especificarlo, shpero a menudo es mejor ser preciso y establecer el "shebangsh".


Los shebangs no son realmente necesarios /bin/sh, aunque no duelen.
zigg

@zigg: tienes razón. Espero que a Chris no le importen mis ediciones ... Nuke o
reedite

@bmike Las ediciones funcionan para mí. En cuanto a los shebangs, mi hábito siempre era especificar porque solía escribir muchos kshscripts en mis días en HP-UX, pero es bueno saber que no es estrictamente necesario.
Chris W. Rea

1
Creo que necesito alejarme de mi declaración anterior sobre la necesidad de shebang (aunque el resto de mi respuesta sigue en pie). Puede ejecutar un script sin shebang desde un shell, pero si usa una execllamada al sistema, obtiene ENOEXEC(error de formato exec ) Lo siento, @bmike, @ ChrisW.Rea. Voy a editar mi respuesta ahora.
zigg
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.