La #!
línea se usa antes de ejecutar el script, luego se ignora cuando se ejecuta el script.
Estás preguntando cuál es la diferencia entre una línea shebang y un comentario ordinario.
Una línea que comienza #!
es tanto un comentario como cualquier otra línea que comienza con #
. Esto es cierto si #!
es la primera línea del archivo o en cualquier otro lugar. #!/bin/sh
tiene un efecto , pero el intérprete no lo lee .
#
no es un comentario en todos los lenguajes de programación, pero, como saben, es un comentario en los shells de estilo Bourne que incluyen sh
y bash
(así como la mayoría de los shells que no son de estilo Bourne, como csh
). También es un comentario en Python . Y es un comentario en una variedad de archivos de configuración que en realidad no son scripts (como /etc/fstab
).
Supongamos que un script de shell comienza con #!/bin/sh
. Ese es un comentario, y el intérprete (el shell) ignora todo en la línea después del #
personaje.
El propósito de una #!
línea no es proporcionar información al intérprete. El propósito de la #!
línea es decirle al sistema operativo (o cualquier proceso que inicie el intérprete) qué usar como intérprete .
Si invoca el script como un archivo ejecutable, por ejemplo, al ejecutar ./script.sh
, el sistema consulta la primera línea para ver si comienza con #!
, seguido de cero o más espacios, seguido de un comando. Si lo hace, ejecuta ese comando con el nombre del script como argumento. En este ejemplo, se ejecuta /bin/sh script.sh
(o, técnicamente /bin/sh ./script.sh
).
Si invoca el script llamando explícitamente al intérprete, la #!
línea nunca se consulta. Entonces, si corres sh script.sh
, la primera línea no tiene efecto. Si script2.sh
la primera línea es #!/usr/games/nibbles
, la ejecución sh script2.sh
no intentará abrir el script en nibbles
(pero lo ./script2.sh
hará).
Notarás que en ninguno de los casos la extensión del script ( .sh
), si tiene una, afecta la forma en que se ejecuta. En un sistema tipo Unix, esto normalmente no afecta la forma en que se ejecuta el script. En algunos otros sistemas, como Windows, el sistema #!
puede ignorar por completo la línea shebang, y la extensión puede determinar qué ejecuta los scripts. (Esto no significa que necesite dar extensiones a sus scripts, pero es una de las razones por las que si lo hace, deberían ser correctas).
#!
fue elegido para cumplir este propósito precisamente porque #
comienza un comentario. La #!
línea es para el sistema, no para el intérprete, y debe ser ignorada por el intérprete.
Línea Shebang para secuencias de comandos Bash
Usted (originalmente) dijo que usaba #!/bin/sh
para los bash
scripts. Solo debe hacer eso si la secuencia de comandos no requiere ninguna de bash
las extensiones: sh
necesita poder ejecutar la secuencia de comandos. sh
no siempre es un enlace simbólico a bash
. A menudo, incluso en todos los sistemas Debian y Ubuntu remotos recientes , sh
es un enlace simbólico a dash
.
Línea Shebang para scripts Python
También dijo (en la primera versión de su pregunta, antes de editar) que comienza con sus scripts Python #!/bin/sh read by the interpretor
. Si lo dices literalmente, entonces definitivamente deberías dejar de hacerlo. Si hello.py
comienza con esa línea, la ejecución se ./hello.py
ejecuta:
/bin/sh read by the interpretor hello.py
/bin/sh
intentará ejecutar un script llamado read
(con by the interpretor hello.py
sus argumentos), read
(con suerte) no será encontrado, y su script Python nunca será visto por un intérprete de Python.
Si está cometiendo este error pero no tiene el problema que estoy describiendo, probablemente esté invocando sus scripts de Python especificando explícitamente el intérprete (por ejemplo, python hello.py
), haciendo que se ignore la primera línea. Cuando distribuye sus scripts a otros, o los usa mucho tiempo después, puede que no esté claro que esto sea necesario para que funcionen. Es mejor arreglarlos ahora. O al menos elimine la primera línea por completo, de modo que cuando no se ejecuten con ./
el mensaje de error tenga sentido.
Para los scripts de Python, si sabe dónde está (o va a estar) el intérprete de Python, puede escribir la #!
línea de la misma manera:
#!/usr/bin/python
O, si se trata de un script de Python 3, debe especificar python3
, ya python
que casi siempre es Python 2 :
#!/usr/bin/python3
Sin embargo, el problema es que si bien /bin/sh
se supone que siempre existe, y /bin/bash
casi siempre existe en los sistemas que bash
vienen con el sistema operativo, Python puede existir en una variedad de lugares.
Por lo tanto, muchos programadores de Python usan esto en su lugar:
#!/usr/bin/env python
(O #!/usr/bin/env python3
para Python 3.)
Esto hace que el script se base en env
estar en el "lugar correcto" en lugar de confiar en python
estar en el lugar correcto. Eso es bueno porque:
env
casi siempre se encuentra en /usr/bin
.
- En la mayoría de los sistemas, lo que
python
debe ejecutar la secuencia de comandos es la que aparece por primera vez en el PATH
. Comenzando hello.py
con #!/usr/bin/env python
make ./hello.py
run /usr/bin/env python hello.py
, que es (virtualmente) equivalente a correr python hello.py
.
La razón por la que no puede usar #!python
es que:
- Desea que el intérprete especificado sea dado por una ruta absoluta (es decir, comenzando con
/
)
- El proceso de llamada se ejecutaría
python
en el directorio actual . Buscar la ruta cuando el comando no contiene una barra oblicua es un comportamiento de shell específico.
Ocasionalmente, un Python u otro script que no sea un script de shell tendrá una línea shebang que comienza #!/bin/sh ...
donde ...
hay algún otro código. Esto a veces es correcto, porque hay algunas formas de invocar el shell compatible con Bourne ( sh
) con argumentos para que invoque un intérprete de Python. (Uno de los argumentos probablemente contendrá python
). Sin embargo, para la mayoría de los propósitos, #!/usr/bin/env python
es más simple, más elegante y es más probable que funcione de la manera que desee.
Shebang Lines en otros idiomas
Muchos lenguajes de programación y secuencias de comandos, y algunos otros formatos de archivo, se usan #
como comentario. Para cualquiera de ellos, un archivo en el lenguaje puede ser ejecutado por un programa que lo toma como argumento especificando el programa en la primera línea después #!
.
En algunos lenguajes de programación, #
normalmente no es un comentario, pero como caso especial se ignora la primera línea si comienza con #!
. Esto facilita el uso de la #!
sintaxis aunque de #
otra manera no hace que una línea sea un comentario.
Líneas Shebang para archivos que no se ejecutan como scripts
Si bien es menos intuitivo, cualquier archivo cuyo formato de archivo puede acomodar una primera línea que comienza con #!
seguido de la ruta completa de un ejecutable puede tener una línea shebang. Si hace esto, y el archivo está marcado como ejecutable, puede ejecutarlo como un programa ... haciendo que se abra como un documento.
Algunas aplicaciones usan este comportamiento intencionalmente. Por ejemplo, en VMware, los .vmx
archivos definen máquinas virtuales. Puede "ejecutar" una máquina virtual como si fuera un script porque estos archivos están marcados como ejecutables y tienen una línea shebang que hace que se abran en una utilidad VMware.
Shebang Lines para archivos que no se ejecutan como scripts pero que, de todos modos, actúan como scripts
rm
elimina archivos No es un lenguaje de script. Sin embargo, #!/bin/rm
se puede ejecutar un archivo que se inicia y está marcado como ejecutable, y cuando lo ejecuta, rm
se invoca y lo elimina.
Esto a menudo se conceptualiza como "el archivo se elimina a sí mismo". Pero el archivo no se está ejecutando en absoluto. Esto se parece más a la situación descrita anteriormente para los .vmx
archivos.
Aún así, debido a que la #!
línea facilita la ejecución de un comando simple (incluidos los argumentos de la línea de comandos), puede realizar algunas secuencias de comandos de esta manera. Como un ejemplo simple de un "script" más sofisticado que #!/bin/rm
, considere:
#!/usr/bin/env tee -a
Esto toma la entrada del usuario de forma interactiva, la devuelve eco al usuario línea por línea y la agrega al final del archivo "script".
¿Útil? No muy. ¿Conceptualmente interesante? ¡Totalmente! Si. (Algo.)
Conceptos de programación / scripting conceptualmente similares (solo por diversión)
#include
. Allí también, el#
no se entiende como un comentario.