¿Por qué todos los archivos de script comienzan con
#!/bin/sh
o con
#!/bin/csh
¿Eso es obligatorio? Cual es el proposito de esto? ¿Y cuál es la diferencia entre los dos?
¿Por qué todos los archivos de script comienzan con
#!/bin/sh
o con
#!/bin/csh
¿Eso es obligatorio? Cual es el proposito de esto? ¿Y cuál es la diferencia entre los dos?
Respuestas:
Esto se conoce como Shebang:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#! intérprete [opcional-arg]
Un shebang solo es relevante cuando un script tiene el permiso de ejecución (por ejemplo, chmod u + x script.sh).
Cuando un shell ejecuta el script, utilizará el intérprete especificado.
Ejemplo:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
La #!línea le dice al kernel (específicamente, la implementación de la execvellamada al sistema) que este programa está escrito en un lenguaje interpretado; el nombre de ruta absoluto que sigue identifica al intérprete. Los programas compilados en código de máquina comienzan con una secuencia de bytes diferente, en la mayoría de los Unix modernos, 7f 45 4c 46( ^?ELF) que los identifica como tales.
Puede poner una ruta absoluta a cualquier programa que desee después de #!, siempre que ese programa no sea en sí mismo un #!script. El kernel reescribe una invocación de
./script arg1 arg2 arg3 ...
donde ./scriptcomienza con, digamos, #! /usr/bin/perlcomo si la línea de comando hubiera sido
/usr/bin/perl ./script arg1 arg2 arg3
O, como ha visto, puede utilizar #! /bin/shpara escribir un guión destinado a ser interpretado por sh.
La #!línea solo se procesa si invoca directamente el script ( ./scripten la línea de comando); el archivo también debe ser ejecutable ( chmod +x script). Si lo hace, sh ./scriptla #!línea no es necesaria (y se ignorará si está presente), y el archivo no tiene que ser ejecutable. El objetivo de la función es permitirle invocar directamente programas en lenguaje interpretado sin tener que saber en qué idioma están escritos. (Sí grep '^#!' /usr/bin/*, descubrirá que una gran cantidad de programas estándar están utilizando esta función).
Aquí hay algunas reglas para usar esta función:
#!deben ser los dos primeros bytes del archivo. En particular, el archivo debe tener una codificación compatible con ASCII (por ejemplo, UTF-8 funcionará, pero UTF-16 no) y no debe comenzar con una "marca de orden de bytes", o el kernel no lo reconocerá como un #!guión.#!debe ser una ruta absoluta (comienza con /). No puede contener espacios, tabulaciones o caracteres de nueva línea.#!y el /. No coloque más de un espacio allí.#!línea, no se expandirán.#! /usr/bin/awk -f), a veces solo es útil ( #! /usr/bin/perl -Tw). Desafortunadamente, no puede poner dos o más argumentos después de la ruta absoluta.#! /usr/bin/env interpreterlugar de #! /absolute/path/to/interpreter. Casi siempre es un error. Hace que el comportamiento de su programa dependa de la $PATHvariable del usuario que invoca el script. Y no todos los sistemas lo tienen enven primer lugar.setuido setgidque no pueden usar #!; deben compilarse en código de máquina. (Si no sabe qué setuides, no se preocupe por esto).Respecto a esto csh, se relaciona shmás o menos como lo hace el sustituto de té avanzado Nutrimat con el té. Tiene (o más bien tuvo; implementaciones modernas de se shhan puesto al día) una serie de ventajas sobre shel uso interactivo, pero usarlo (o su descendiente tcsh) para la creación de scripts es casi siempre un error . Si es nuevo en la creación de scripts de shell en general, le recomiendo que lo ignore y se concentre en sh. Si está utilizando un cshpariente como su shell de inicio de sesión, cambie a basho zsh, de modo que el lenguaje de comandos interactivo sea el mismo que el lenguaje de scripting que está aprendiendo.
#!; no hay comentarios sobre si eso es un buen estilo. Vea esta pregunta y mi respuesta para una discusión de los pros y los contras del #!/usr/bin/envtruco.
#!/usr/bin/envera lo correcto, pero sigo siendo mi opinión de que casi siempre es una mala idea.
Esto define qué shell (intérprete de comandos) está utilizando para interpretar / ejecutar su script. Cada shell es ligeramente diferente en la forma en que interactúa con el usuario y ejecuta scripts (programas).
Cuando escribe un comando en el indicador de Unix, está interactuando con el shell.
Por ejemplo, se #!/bin/cshrefiere a C-shell, /bin/tcsht-shell, /bin/bashbash shell, etc.
Puede saber qué shell interactivo está utilizando
echo $SHELL
comando, o alternativamente
env | grep -i shell
Puede cambiar su shell de comandos con el chshcomando.
Cada uno tiene un conjunto de comandos y una forma de asignar variables ligeramente diferentes y su propio conjunto de construcciones de programación. Por ejemplo, la instrucción if-else con bash se ve diferente a la del C-shell.
Esta página puede ser de interés ya que se "traduce" entre los comandos / sintaxis bash y tcsh.
El uso de la directiva en el script de shell le permite ejecutar programas utilizando un shell diferente. Por ejemplo, uso el tcshshell de forma interactiva, pero a menudo ejecuto scripts bash usando / bin / bash en el archivo de script.
Aparte:
Este concepto se extiende también a otros scripts. Por ejemplo, si programa en Python, pondría
#!/usr/bin/python
en la parte superior de su programa Python
#! $SHELL? ¿Pondría esto el caparazón correcto en el Shebang?
!#/bin/bashdirectiva , por ejemplo . Le dice al sistema qué shell usar para ejecutar su script de shell.
$SHELLno necesariamente le dice qué shell está ejecutando en este momento; normalmente le dice su shell predeterminado . tcsh establece $versiony $tcsh; conjuntos de bash $BASH_VERSION. No todas las carcasas tienen necesariamente mecanismos similares.
#!línea tiene que coincidir con la sintaxis del script, no con el shell interactivo utilizado por quien ejecuta el script.
#!/bin/csh -f; el-fle dice al shell que no obtenga el usuario.loginy.cshrc, lo que hace que el script se ejecute más rápido y evita dependencias en la configuración del usuario. (O mejor aún, no escriba scripts csh). No lo utilice-fpara scripts sh o bash; no tiene el mismo significado.