Tengo un proyecto compuesto por unos 20 .sh
archivos pequeños . Los denomino "pequeños" porque generalmente, ningún archivo tiene más de 20 líneas de código. Tomé un enfoque modular porque, por lo tanto, soy fiel a la filosofía de Unix y es más fácil para mí mantener el proyecto.
Al comienzo de cada .sh
archivo, pongo #!/bin/bash
.
En pocas palabras, entiendo que las declaraciones de script tienen dos propósitos:
- Ayudan al usuario a recordar qué shell se necesita para ejecutar el archivo (por ejemplo, después de algunos años sin usar el archivo).
- Se aseguran de que el script se ejecute solo con un determinado shell (Bash en ese caso) para evitar un comportamiento inesperado en caso de que se use otro shell.
Cuando un proyecto comienza a crecer de, digamos, 5 archivos a 20 archivos o de 20 a 50 archivos (no este caso, sino solo para demostrarlo) tenemos 20 líneas o 50 líneas de declaraciones de guiones. Admito que, aunque puede ser divertido para algunos, me parece un poco redundante usar 20 o 50 en lugar de decir solo 1 por proyecto (tal vez en el archivo principal del proyecto).
¿Hay alguna forma de evitar esta supuesta redundancia de 20 o 50 o un número mucho mayor de líneas de declaraciones de script utilizando alguna declaración de script "global", en algún archivo principal?
fuente
/bin/bash -x "$script"
Respuestas:
Aunque su proyecto ahora puede consistir únicamente en 50 scripts de Bash, tarde o temprano comenzará a acumular scripts escritos en otros idiomas, como Perl o Python (por los beneficios que tienen estos lenguajes de scripts que Bash no tiene).
Sin una línea adecuada
#!
en cada secuencia de comandos, sería extremadamente difícil utilizar las diversas secuencias de comandos sin saber qué intérprete utilizar. No importa si cada script se ejecuta desde otros scripts , esto solo mueve la dificultad de los usuarios finales a los desarrolladores. Ninguno de estos dos grupos de personas debería necesitar saber en qué idioma se escribió un guión para poder usarlo.Los scripts de Shell ejecutados sin una línea
#!
y sin un intérprete explícito se ejecutan de diferentes maneras dependiendo de qué shell los invoque (vea, por ejemplo, la pregunta ¿Qué intérprete de shell ejecuta un script sin shebang? Y especialmente la respuesta de Stéphane ), que no es lo que desea en un entorno de producción (desea un comportamiento consistente y posiblemente incluso portabilidad).Los scripts ejecutados con un intérprete explícito serán ejecutados por ese intérprete independientemente de lo que
#!
diga la línea. Esto causará problemas más adelante si decide volver a implementar, por ejemplo, un script Bash en Python o en cualquier otro idioma.Debes gastar esas teclas adicionales y siempre agregar una línea
#!
a cada script.En algunos entornos, hay textos legales de múltiples párrafos en cada secuencia de comandos en cada proyecto. Sé muy feliz de que solo sea una línea
#!
que se sienta "redundante" en tu proyecto.fuente
#!
línea tan pronto como el archivo tenga permiso ejecutable y no sea cargado por un intérprete, sino por el shell. Es decir,/path/to/myprog.pl
ejecuta un programa perl si la#!
línea está presente (apuntando al intérprete perl) y el archivo tiene permiso de ejecución.No entiendes el punto de
#!
. En realidad, es una directiva para el sistema operativo ejecutar este programa bajo el intérprete definido.Entonces podría
#!/usr/bin/perl
existir un script y el programa resultante puede ejecutarse como./myprogram
y podría usarse el intérprete perl. Similar#!/usr/bin/python
haría que un programa se ejecute bajo python.Entonces la línea
#!/bin/bash
le dice al sistema operativo que ejecute este programa en bash.Aquí hay un ejemplo:
Entonces, a pesar de que mi shell es ksh, el programa "x" se ejecuta bajo bash debido a la
#!
línea, y podemos verlo explícitamente en la lista de procesos.fuente
ps -aux
puede dar advertencia,ps
da la advertenciaWarning: bad syntax, perhaps a bogus '-'?
.ps
suooprts la sintaxis de argumento BSD y UXIX .-aux
está mal UNIX Stephen probablemente significaaux
cuál es el BSD correctops
muestra la llamada debash
) no la sintaxis explícita; (2)ps -aux
funciona perfectamente en CentOS 7 y Debian 9 sin advertencias; ese cut'n'paste fue exactamente el resultado de mi máquina; toda la discusión sobre si-
es necesario o no es aplicable a versiones anteriores de Linux Procps, no a las versiones actuales.En
.sh
Lo que es malo es
.sh
al final del nombre del archivo.Imagine que reescribe uno de los scripts en python.
Bueno, ahora tiene que cambiar la primera línea para que
#!/usr/bin/python3
esto no sea tan malo, ya que también tuvo que cambiar cualquier otra línea de código en el archivo. Sin embargo, también debe cambiar el nombre del archivo deprog.sh
aprog.py
. Y luego tiene que encontrar en todas partes en los otros scripts, y todos sus scripts de usuario (los que ni siquiera sabía que existían), y cambiarlos para usar el nuevo script.sed -e 's/.sh/.py/g'
puede ayudar a los que conoces. Pero ahora su herramienta de control de revisiones muestra un cambio en muchos archivos no relacionados.Alternativamente hacerlo de la manera Unix y el nombre del programa
prog
noprog.sh
.En
#!
Si tiene el correcto
#!
y configure el permiso / modo para incluir la ejecución. Entonces no necesita conocer al intérprete. La computadora lo hará por usted.Para sistemas que no son GNU, lea el manual para
chmod
(y aprenda octal), tal vez léalo de todos modos.fuente
.image
para fotos..audio
para sonido, etc. De este modo se le dice qué es pero no sobre la implementación / codificación.launch-missiles
odelete-project-and-make-manager-pissed
no quiero "simplemente ejecutarlo" cuando solo tenía curiosidad sobre el idioma :)file
comando. reconoce la mayoría de los tipos de archivos.Probablemente valga la pena señalar que esto está bastante mal. La línea hashbang de ninguna manera le impide intentar alimentar el archivo a un intérprete / intérprete incorrecto:
(o de manera similar con
awk -f array.sh
etc.)Pero, en cualquier caso, otro enfoque de la modularidad sería definir funciones de shell en los archivos, una función por archivo, si lo desea, y luego
source
los archivos del programa principal. De esa manera, no necesitarías hashbangs: serían tratados como cualquier otro comentario, y todo se ejecutaría usando el mismo shell. La desventaja sería que necesitaríasource
los archivos con las funciones (por ejemplofor x in functions/*.src ; do source "$x" ; done
), y todos se ejecutarían con el mismo shell, por lo que no podría reemplazar directamente uno de ellos con una implementación de Perl.fuente
Hay - se llama portabilidad o cumplimiento POSIX. Esfuércese por escribir siempre scripts de manera portátil y neutral para el shell, aprovéchelos solo de un script que use
#!/bin/sh
o cuando lo use de forma/bin/sh
interactiva (o al menos un shell compatible con POSIX comoksh
).Sin embargo, los scripts portátiles no lo salvan de:
/bin/sh
scriptcsh
.Si puedo expresar mi opinión, "evitar la redundancia" eliminando
#!
es un objetivo equivocado. El objetivo debe ser un rendimiento consistente y, en realidad, un script de trabajo que funcione, y considere casos de esquina, siga ciertas reglas generales como no-parsing-ls o siempre-citando variables-a menos que se necesite dividir palabras .Realmente no son para el usuario: son para que el sistema operativo ejecute un intérprete adecuado. "Apropiado" en este caso, significa que OS encuentra lo que está en shebang; si el código debajo es incorrecto, es culpa del autor. En cuanto a la memoria del usuario, no creo que el "usuario" de programas como Microsoft Word o Google Chrome haya necesitado saber en qué idioma están escritos los programas; Los autores pueden necesitar.
Por otra parte, los scripts escritos de forma portátil pueden eliminar la necesidad de recordar incluso qué shell usó originalmente, porque los scripts portátiles deberían funcionar en cualquier shell compatible con POSIX.
Ellos no. Lo que realmente evita un comportamiento inesperado es escribir scripts portátiles.
fuente
La razón por la que necesita colocar
#!/bin/bash
en la parte superior de cada script es que lo está ejecutando como un proceso separado.Cuando ejecuta un script como un nuevo proceso, el sistema operativo ve que es un archivo de texto (en lugar de un ejecutable binario) y necesita saber qué intérprete ejecutar. Si no lo dice, el sistema operativo solo puede adivinar, utilizando su configuración predeterminada (que un administrador puede cambiar). Entonces, la
#!
línea (además de agregar permisos ejecutables, por supuesto) convierte un archivo de texto simple en un ejecutable que se puede ejecutar directamente, con la confianza de que el sistema operativo sabe qué hacer con él.Si desea eliminar la
#!
línea, sus opciones son:Ejecute el script directamente (como lo está haciendo ahora) y espere que el intérprete predeterminado coincida con el script: probablemente esté seguro en la mayoría de los sistemas Linux, pero no sea portátil a otros sistemas (por ejemplo, Solaris), y se puede cambiar a cualquier cosa (¡incluso podría configurarlo para que se ejecute
vim
en el archivo!).Ejecute el script usando
bash myscript.sh
. Esto funciona bien, pero debe especificar la ruta al script, y es desordenado.Obtenga el script utilizando
. myscript.sh
, que ejecuta el script dentro del proceso actual de interpretación (es decir, no como un subproceso). Pero esto seguramente requerirá modificaciones a sus scripts, y los hace menos modulares / reutilizables.En los casos 2 y 3, el archivo no necesita (y no debería tener) permisos de ejecución, y darle un sufijo
.sh
(o.bash
) es una buena idea.Pero ninguna de esas opciones se ve bien para su proyecto, ya que dijo que desea mantener sus scripts modulares (=> independientes y autónomos), por lo que debe mantener su
#!/bin/bash
línea en la parte superior de los scripts.En su pregunta, también dijo que sigue la filosofía de Unix. Si eso es cierto, entonces debes aprender para qué
#!
es realmente la línea, ¡y seguir usándola en cada script ejecutable!fuente
then you should learn what the #! line is really for, and keep using it in every executable script!
. Uno puede seguir la filosofía de los Estados Unidos hasta cierto punto de conocimiento. Después de todas estas respuestas, entendí por qué se puede incluir en ese término. Sugiero editar la respuesta, reemplazándola con "Vea el shebang como una parte interna de la Filosofía Unix que respeta y adopta".