Para un script csh, debe usar #!/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.
@Kolob Canyon no es necesario, pero puede ayudar a algunos editores con el resaltado de sintaxis (aunque generalmente hay otras formas de lograr lo mismo): unix.stackexchange.com/a/88730/193985
Braham Snyder
42
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:
El #!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.
La ruta posterior #!debe ser una ruta absoluta (comienza con /). No puede contener espacios, tabulaciones o caracteres de nueva línea.
Es de buen estilo, pero no obligatorio, poner un espacio entre el #!y el /. No coloque más de un espacio allí.
No puede poner variables de shell en la #!línea, no se expandirán.
Puede poner un argumento de línea de comando después de la ruta absoluta, separado de él por un solo espacio. Al igual que la ruta absoluta, este argumento no puede contener espacios, tabulaciones o caracteres de nueva línea. A veces esto es necesario para que las cosas funcionen ( #! /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.
Algunas personas le dirán que use en #! /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.
Programas que necesitan privilegios 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.
Las versiones recientes de Linux permiten que el intérprete especificado sea un script. Es una práctica común omitir el espacio después de #!; 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.
Keith Thompson
@KeithThompson Tengo la impresión de que Linux es la única variante común de Unix que permite que el intérprete sea un script, por lo que todavía no es algo en lo que confiar. Desde que escribí esto, me he encontrado con una situación en la que #!/usr/bin/envera lo correcto, pero sigo siendo mi opinión de que casi siempre es una mala idea.
zwol
4
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
Entonces, ¿es necesario? ¿Cómo sé qué shell estoy usando realmente?
One Two Three
Entonces, si estoy escribiendo los scripts para que alguien los use en su máquina, y no sé qué shell están usando. (Esta persona, desafortunadamente, no tiene ni idea de estas cosas, por lo que todo lo que puede hacer es ejecutar el script sin cambiar nada). ¿Puedo hacer algo como #! $SHELL? ¿Pondría esto el caparazón correcto en el Shebang?
One Two Three
1
@OneTwoThree La mayoría de los sistemas tienen los shells estándar, si escribe un script bash o csh estará bien. No importa qué caparazón estén usando de forma interactiva , esa es la belleza de la !#/bin/bashdirectiva , por ejemplo . Le dice al sistema qué shell usar para ejecutar su script de shell.
Levon
El valor de $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.
Keith Thompson
1
@OneTwoThree: La #!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-f
le dice al shell que no obtenga el usuario.login
y.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-f
para scripts sh o bash; no tiene el mismo significado.Respuestas:
Esto se conoce como
Shebang
:http://en.wikipedia.org/wiki/Shebang_(Unix)
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
fuente
La
#!
línea le dice al kernel (específicamente, la implementación de laexecve
llamada 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 dedonde
./script
comienza con, digamos,#! /usr/bin/perl
como si la línea de comando hubiera sidoO, como ha visto, puede utilizar
#! /bin/sh
para escribir un guión destinado a ser interpretado porsh
.La
#!
línea solo se procesa si invoca directamente el script (./script
en la línea de comando); el archivo también debe ser ejecutable (chmod +x script
). Si lo hace,sh ./script
la#!
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 interpreter
lugar de#! /absolute/path/to/interpreter
. Casi siempre es un error. Hace que el comportamiento de su programa dependa de la$PATH
variable del usuario que invoca el script. Y no todos los sistemas lo tienenenv
en primer lugar.setuid
osetgid
que no pueden usar#!
; deben compilarse en código de máquina. (Si no sabe quésetuid
es, no se preocupe por esto).Respecto a esto
csh
, se relacionash
más o menos como lo hace el sustituto de té avanzado Nutrimat con el té. Tiene (o más bien tuvo; implementaciones modernas de sesh
han puesto al día) una serie de ventajas sobresh
el uso interactivo, pero usarlo (o su descendientetcsh
) 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 ensh
. Si está utilizando uncsh
pariente como su shell de inicio de sesión, cambie abash
ozsh
, de modo que el lenguaje de comandos interactivo sea el mismo que el lenguaje de scripting que está aprendiendo.fuente
#!
; 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/env
truco.#!/usr/bin/env
era 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/csh
refiere a C-shell,/bin/tcsh
t-shell,/bin/bash
bash shell, etc.Puede saber qué shell interactivo está utilizando
echo $SHELL
comando, o alternativamente
Puede cambiar su shell de comandos con el
chsh
comando.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
tcsh
shell 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
fuente
#! $SHELL
? ¿Pondría esto el caparazón correcto en el Shebang?!#/bin/bash
directiva , por ejemplo . Le dice al sistema qué shell usar para ejecutar su script de shell.$SHELL
no necesariamente le dice qué shell está ejecutando en este momento; normalmente le dice su shell predeterminado . tcsh establece$version
y$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.