bash - hello - script in sh
¿Debo usar un Shebang con scripts Bash? (7)
Estoy usando Bash
$ echo $SHELL
/bin/bash
y hace aproximadamente un año, dejé de usar Shebangs con mis scripts de Bash. ¿Puedo beneficiarme del uso de #!/bin/sh
o #!/bin/bash
?
Actualización: en ciertas situaciones, un archivo solo se trata como un script con el ejemplo de Shebang
$ cat foo.sh
ls
$ cat bar.sh
#!/bin/sh
ls
$ file foo.sh bar.sh
foo.sh: ASCII text
bar.sh: POSIX shell script, ASCII text executable
$ SHELL y #! / Bin / bash o #! / Bin / sh son diferentes.
Para comenzar, #! / Bin / sh es un enlace simbólico a / bin / bash en la mayoría de los sistemas Linux (en Ubuntu ahora es / bin / dash)
Pero sobre si comenzar con / bin / sh o / bin / bash:
Bash y sh son dos conchas diferentes. Básicamente bash es sh, con más características y mejor sintaxis. La mayoría de los comandos funcionan de la misma manera, pero son diferentes.
Solo asuma que si está escribiendo un script de bash, quédese con / bin / bash y not / sh porque pueden surgir problemas.
$ SHELL no refleja necesariamente el shell actualmente en ejecución. En cambio, $ SHELL es el shell preferido del usuario, que generalmente es el que se establece en / etc / passwd. Si inicia un shell diferente después de iniciar sesión, no necesariamente puede esperar que $ SHELL coincida más con el shell actual.
Esto es mío, por ejemplo, pero también podría ser / root: / bin / dash o / root: / bin / sh dependiendo de la shell que haya ingresado en passwd. Así que para evitar cualquier problema, mantenga el archivo de contraseña en / bin / bash y luego use $ SHELL vs. #! / Bin / bash no importaría tanto.
root@kali:~/Desktop# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
Fuentes: http://shebang.brandonmintern.com/bourne-is-not-bash-or-read-echo-and-backslash/ https://unix.stackexchange.com/questions/43499/difference-between-echo-shell-and-which-bash http://man.cx/sh http://man.cx/bash
Además de lo que dijeron los demás, shebang también habilita el resaltado de sintaxis en algunos editores de texto, por ejemplo vim.
El encabezado es útil ya que especifica qué shell usar cuando se ejecuta el script. Por ejemplo, #!/bin/zsh
cambiaría el shell a zsh en lugar de bash, donde puede usar diferentes comandos.
Por ejemplo, esta página especifica lo siguiente:
Al usar #! / Bin / sh, el shell Bourne predeterminado en la mayoría de las variantes comerciales de UNIX, hace que el script sea portátil a máquinas que no sean Linux, aunque se sacrifican las características específicas de Bash ...
En sistemas similares a UNIX, siempre debe iniciar scripts con una línea shebang. El execve
llamada del sistema (que es responsable de iniciar los programas) se basa en un ejecutable que tiene un encabezado ejecutable o una línea shebang.
De la execve página de manual de FreeBSD:
The execve() system call transforms the calling process into a new process. The new process is constructed from an ordinary file, whose name is pointed to by path, called the new process file. [...] This file is either an executable object file, or a file of data for an interpreter. [...] An interpreter file begins with a line of the form: #! interpreter [arg] When an interpreter file is execve''d, the system actually execve''s the specified interpreter. If the optional arg is specified, it becomes the first argument to the interpreter, and the name of the originally execve''d file becomes the second argument
Del mismo modo desde la página de manual de Linux :
execve () ejecuta el programa apuntado por nombre de archivo. el nombre de archivo debe ser un ejecutable binario o una secuencia de comandos que comience con una línea del formulario:
#! interpreter [optional-arg]
De hecho, si un archivo no tiene el "número mágico" correcto en su encabezado (como un encabezado ELF o #!
), execve
fallará con el error ENOEXEC (nuevamente de la página de manual execve de FreeBSD):
[ENOEXEC] El nuevo archivo de proceso tiene el permiso de acceso adecuado, pero tiene un número mágico no válido en su encabezado.
Si el archivo tiene permisos ejecutables, pero no hay una línea de shebang pero parece ser un archivo de texto, el comportamiento depende del shell en el que se esté ejecutando.
La mayoría de los shells parecen iniciar una nueva instancia de sí mismos y alimentar el archivo, ver más abajo.
Dado que no hay garantía de que el script se haya escrito para ese shell, esto puede funcionar o fallar espectacularmente.
Desde tcsh(1) :
On systems which do not understand the `#!'' script interpreter conven‐ tion the shell may be compiled to emulate it; see the version shell variable. If so, the shell checks the first line of the file to see if it is of the form `#!interpreter arg ...''. If it is, the shell starts interpreter with the given args and feeds the file to it on standard input.
If the program is not a normal executable file (i.e., if it
does not begin with the “magic number” whose ASCII representation is
“#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
be a text file, the shell will run a new instance of sh to interpret it.
Desde bash (1):
If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell script, a file containing shell commands. A subshell is spawned to execute it.
No siempre puede depender de la ubicación de un programa no estándar como bash. He visto bash en /usr/bin
, /usr/local/bin
, /opt/fsf/bin
y /opt/gnu/bin
para nombrar algunos.
Por lo tanto, generalmente es una buena idea usar env
;
#!/usr/bin/env bash
Si quieres que tu script sea portátil, usa sh
lugar de bash
.
#!/bin/sh
Si bien los estándares como POSIX no garantizan las rutas absolutas de las utilidades estándar, la mayoría de los sistemas similares a UNIX parecen tener sh
in /bin
y env
en /usr/bin
.
Los scripts siempre deben comenzar con una línea shebang. Si un script no comienza con esto, entonces puede ser ejecutado por el shell actual. Pero eso significa que si alguien que usa tu script está ejecutando un shell diferente al tuyo, el script puede comportarse de manera diferente. Además, significa que la secuencia de comandos no se puede ejecutar directamente desde un programa (por ejemplo, la llamada al sistema C exec()
, o find -exec
), tiene que ejecutarse desde un shell.
Quizás te interese una descripción temprana de Dennis M. Ritchie ( dmr
) que inventó el #!
:
De uucp Jue 10 de enero 01:37:58 1980
.> De dmr Jue 10 de enero 04:25:49 1980 alejado de la investigación
Se ha cambiado el sistema para que si un archivo se está ejecutando comience con los caracteres mágicos #! , se entiende que el resto de la línea es el nombre de un intérprete para el archivo ejecutado. Anteriormente (y de hecho todavía) el shell hizo gran parte de este trabajo; se ejecutó automáticamente en un archivo de texto con modo ejecutable cuando el nombre del archivo de texto se escribió como un comando. Poner la instalación en el sistema da los siguientes beneficios.
1) Hace que los scripts de shell se parezcan más a los archivos ejecutables reales, ya que pueden ser el tema de ''exec''.
2) Si ejecuta un ''ps'' mientras se ejecuta un comando de este tipo, su nombre real aparece en lugar de ''sh''. Asimismo, la contabilidad se realiza sobre la base del nombre real.
3) Los scripts de shell pueden ser set-user-ID.
4) Es más simple tener carcasas alternativas disponibles; Por ejemplo, si le gusta el csh de Berkeley, no hay duda sobre qué shell interpretará un archivo.
5) Permitirá que otros intérpretes encajen mejor.
Para aprovechar esta maravillosa oportunidad, ponte
#! /bin/sh
en el margen izquierdo de la primera línea de sus shell scripts. ¡Espacios en blanco después! están bien. Utilice una ruta completa (no se realiza ninguna búsqueda). En este momento, toda la línea está restringida a 16 caracteres, pero este límite se elevará.
Espero que esto ayude
Si escribe scripts de bash , es decir, scripts no portátiles que contienen bashismos, debe seguir utilizando el
#!/bin/bash
shebang solo para asegurarse de que se utiliza el intérprete correcto. No debe reemplazar el shebang por#!/bin/sh
ya que bash se ejecutará en el modo POSIX, por lo que algunos de sus scripts podrían comportarse de manera diferente.Si escribe scripts portátiles , es decir, solo los scripts que utilizan las utilidades POSIX y sus opciones compatibles, puede seguir utilizando
#!/bin/sh
en su sistema (es decir, uno donde/bin/sh
es un shell POSIX).Si escribe scripts POSIX que se ajustan estrictamente para distribuirlos en varias plataformas y está seguro de que solo se lanzarán desde un sistema compatible con POSIX, puede y probablemente debería eliminar el shebang como se indica en el estándar POSIX:
Tal como está, una aplicación estrictamente conforme no debe usar "#!" como los dos primeros caracteres del archivo.
La razón es que el estándar POSIX no obliga a /bin/sh
a ser el shell compatible con POSIX, por lo que no hay una forma portátil de especificar su ruta en un shebang. En este tercer caso, para poder utilizar la sintaxis ''find-exec'' en sistemas que no pueden ejecutar un script ejecutable sin shebangless, puede simplemente especificar el intérprete en el comando find, por ejemplo:
find /tmp -name "*.foo" -exec sh -c ''myscript "$@"'' sh {} +
Aquí, como se especifica sh
sin una ruta, se ejecutará el shell POSIX.