¿Por qué necesita poner #! / Bin / bash al comienzo de un archivo de script?

487

He hecho scripts de Bash antes y todos funcionaron bien sin #!/bin/bashal principio.

¿Cuál es el punto de ponerlo? ¿Las cosas serían diferentes?

Además, ¿cómo se pronuncia #? Sé que !se pronuncia como "explosión".

¿Cómo se #!pronuncia?

nodo ninja
fuente
8
No es necesario y no debe hacerlo a menos que no tenga otra opción. Use '#! / Bin / sh' mientras pueda y conozca la diferencia entre un shell (POSIX) y bash. Llegará un día antes de que su currículum crezca demasiado cuando se encuentre en un sistema con un shell diferente y aún desee que sus scripts funcionen.
Jens
50
Se pronuncia "Hash-Bang" o "She-Bang".
Beachhouse
22
Creo que vale la pena señalar que esto solo se ejecuta si ejecuta su script como ejecutable. Entonces, si configura el indicador ejecutable y luego escribe ./yourscript.extension, por ejemplo, ./helloworld.pyo ./helloworld.sh, buscará el intérprete en esa línea superior, que sería #!/bin/pythono !#/bin/bash, mientras que al ejecutar el script como python helloworld.py, la primera línea no se observará porque está comentada fuera. Por lo tanto, es una secuencia especial para el shell / kernel.
JFA
@JFA ¿hay un cambio en la secuencia entre bash y python, cuando se usa! # Para python y #! para bash?
AAI
1
@AjeyaAnand no, fue un error, buena captura
JFA

Respuestas:

426

Es una convención, por lo que el shell * nix sabe qué tipo de intérprete ejecutar.

Por ejemplo, los sabores más antiguos de ATT estaban predeterminados en sh (el shell Bourne), mientras que las versiones más antiguas de BSD estaban en csh (el shell C).

Incluso hoy (donde la mayoría de los sistemas ejecutan bash, el "Bourne Again Shell" ), los scripts pueden estar en bash, python, perl, ruby, PHP, etc. Por ejemplo, puede ver #!/bin/perlo#!/bin/perl5 .

PD: El signo de exclamación ( !) se llama cariñosamente "explosión" . El símbolo de comentario de shell ( #) a veces se denomina "hash" .

PPS: Recuerde: bajo * nix, asociar un sufijo con un tipo de archivo es simplemente una convención , no una "regla" . Un ejecutable puede ser un programa binario, cualquiera de un millón de tipos de script y otras cosas también. De ahí la necesidad de #!/bin/bash.

paulsm4
fuente
1
Descubrí algo más útil, $ #. ¿Cómo se llama eso?
nodo ninja
9191
El shebang no es una convención de shell , es interpretado por el kernel cuando maneja la execve(2)llamada al sistema; entonces el shebang es una convención del núcleo , no una concha.
Basile Starynkevitch
10
Además, ayuda a algunos editores como Vim a determinar el idioma para resaltar la sintaxis si el archivo no tiene una extensión. Sin el shebang, Vim mostrará un script bash igual que el archivo de texto sin formato.
Aaron Blenkush
1
Me hace preguntarme si necesitas agregar #!/bin/shcosas como .profiley cosas que se ejecutan onload
Kolob Canyon
55
Entonces ... ¿ hash-bang-slash-bin-slash-bash ?
Bernat el
135

Para ser más precisos, el shebang #! , cuando son los primeros dos bytes de un archivo ejecutable ( x modo ), es interpretado por la llamada al sistema execve (2) (que ejecuta programas). Pero la especificación POSIX paraexecve no mencionar el shebang.

Debe ir seguido de una ruta de archivo de un intérprete ejecutable (que por cierto podría ser relativo, pero a menudo es absoluto).

Un buen truco (o quizás no tan bueno ) para encontrar un intérprete (por ejemplo python) en el usuario $PATHes usar el envprograma (siempre en /usr/bin/envtodos los Linux) como por ejemplo

 #!/usr/bin/env python

Cualquier ejecutable ELF puede ser un intérprete. ¡Incluso podrías usar #!/bin/cato #!/bin/truesi quisieras! (pero eso a menudo sería inútil)

Basile Starynkevitch
fuente
8
Vea esta pregunta para una discusión sobre el #!/usr/bin/envhack.
Keith Thompson
si quiero pasar un argumento a python, ¿cómo hago eso realmente quiero ejecutar #!/usr/bin/env bash -x? Cómo puedo hacer eso ?
indianwebdevil
es simple, yo mismo lo encontré, solo agregue el parámetro después de eso#!/usr/bin/env bash -x
indianwebdevil
bashes casi siempre /bin/bashasí que tu shebang debería ser#!/bin/bash -x
Basile Starynkevitch
50

Se llama shebang . En unix-speak, # se llama sharp (como en música) o hash (como hashtags en twitter), y! se llama explosión. (¡De hecho, puede hacer referencia a su comando de shell anterior con !!, llamado bang-bang). Entonces, cuando se juntan, obtienes haSH-BANG, o shebang.

La parte después del #! le dice a Unix qué programa usar para ejecutarlo. Si no se especifica, intentará con bash (o sh, o zsh, o lo que sea su variable $ SHELL), pero si está allí, usará ese programa. Además, # es un comentario en la mayoría de los idiomas, por lo que la línea se ignora en la ejecución posterior.

austin1howard
fuente
2
Si ya estoy en bash, ¿comienza otra instancia de bash si ve #! / Bin / bash? ¿Qué pasa si ya estoy en bash y lo dejo afuera? ¿Hay alguna diferencia?
nodo ninja el
2
@javascriptninja de cualquier manera, inicia un nuevo shell bash. En el caso de bash, realmente no hay ninguna diferencia, siempre y cuando ya estés usando bash. El shebang solo realmente importa si (a) necesita ejecutar algo que no es solo un shell, como python o perl, o (b) no usa el shell bash (es decir, usa zsh) pero necesita ejecutar algo que requiere ejecutarse en bash.
austin1howard
Sin embargo, en mi opinión, es una buena práctica incluir el shebang, solo para que alguien que lea el código sepa lo que está sucediendo.
austin1howard
2
Incorrecto: execve(2)syscall no usa la $SHELLvariable. Es el núcleo el que interpreta el shebang.
Basile Starynkevitch
1
@BasileStarynkevitch que es correcto, el cargador de elfos en el núcleo interpreta el shebang. Estaba diciendo que $ SHELL se usaría si no se proporcionaba shebang.
austin1howard
19

El shebang es una directiva para que el cargador use el programa que se especifica después #!del intérprete para el archivo en cuestión cuando intenta ejecutarlo. Entonces, si intenta ejecutar un archivo llamado foo.shque tiene #!/bin/bashen la parte superior, el comando real que se ejecuta es/bin/bash foo.sh . Esta es una forma flexible de utilizar diferentes intérpretes para diferentes programas. Esto es algo implementado a nivel de sistema y la API de nivel de usuario es la convención shebang.

También vale la pena saber que el shebang es un número mágico , uno legible por humanos que identifica el archivo como un guión para el intérprete dado.

Su punto sobre "trabajar" incluso sin el shebang es solo porque el programa en cuestión es un script de shell escrito para el mismo shell que el que está utilizando. Por ejemplo, podría escribir un archivo javascript y luego poner un #! /usr/bin/js(o algo similar) para tener un "script de Shell" de javascript.

Noufal Ibrahim
fuente
18

El sistema operativo toma shell predeterminado para ejecutar su script de shell. Al mencionar la ruta del shell al comienzo del script, le está pidiendo al sistema operativo que use ese shell en particular. También es útil para la portabilidad .

Balaswamy Vaddeman
fuente
15

Cada distribución tiene un shell predeterminado. Bash es el valor predeterminado en la mayoría de los sistemas. Si trabaja en un sistema que tiene un shell predeterminado diferente, entonces los scripts podrían no funcionar según lo previsto si están escritos específicamente para Bash.

Bash ha evolucionado a lo largo de los años tomando código de kshy sh.

Agregar #!/bin/bashcomo la primera línea de su secuencia de comandos, le dice al sistema operativo que invoque lo especificado shellpara ejecutar los comandos que siguen en la secuencia de comandos.

#! a menudo se conoce como "hash-bang", "she-bang" o "sha-bang".

jaypal singh
fuente
9

Se llama shebang . Consiste en un signo de número y un signo de exclamación (#!), Seguido de la ruta completa al intérprete como / bin / bash. Todos los scripts bajo UNIX y Linux se ejecutan usando el intérprete especificado en una primera línea.

Uday Sawant
fuente
0

Puede ser útil para alguien que usa un sistema diferente que no tiene esa biblioteca fácilmente disponible. Si eso no se declara y tiene algunas funciones en su script que no son compatibles con ese sistema, debe declarar # / bin / bash. Me he encontrado con este problema antes en el trabajo y ahora solo lo incluyo como práctica.

Beardy
fuente