¿Hay alguna razón para tener un shebang apuntando a / bin / sh en lugar de / bin / bash?


53

En la mayoría de los scripts de shell que he visto (además de los que no he escrito yo mismo), noté que el shebang está configurado en #!/bin/sh. Esto realmente no me sorprende en los scripts más antiguos, pero también está allí en scripts bastante nuevos.

¿Hay alguna razón para preferir /bin/shmás /bin/bash, ya que bashes casi omnipresente, y con frecuencia por defecto, en muchas máquinas Linux y BSD que se remontan a más de una década?


23
Es una buena parte usar /bin/shsi no usa bashfunciones específicas . Un día podría tener que usar uno de sus scripts en un sistema en el que no está instalado (servidor remoto, computadora integrada ...)
Mathieu

1
en general, debe evitar hacer preguntas que se presten a respuestas basadas en la opinión (que es la única forma posible en que creo que esta pregunta puede responderse, pero esa es solo mi opinión ) .
mikeserv

99
Creo que es posible responder a esta pregunta sin involucrar mera opinión, señalando al menos a dos organizaciones que abordaron esta cuestión durante varios años y observando la historia y el resultado. Con mucha lectura adicional adjunta, para arrancar. ☺
JdeBP

3
@JulesMazur ...the answers so far are fairly subjective...Una declaración "subjetiva" se basa esencialmente en la opinión por definición. /bin/bashsolo debe usarse cuando bash es explícitamente necesario. En más de 40 años como desarrollador, mucho antes bash, casi nunca lo necesitaba explícitamente , excepto durante las pruebas. (También me esfuerzo por evitar las extensiones de shell, pero la mayoría de mis scripts están destinados a la distribución). Muchos scripts en la red también deberían estar destinados a un uso amplio.
user2338816

2
@ user2338816 mi mal, quise decir objetivo . Gracias por tus puntos!
Julio

Respuestas:


83
  1. Hay sistemas que no envían bash por defecto (por ejemplo, FreeBSD).
  2. Incluso si está instalado bash, es posible que no esté ubicado en /bin.
  3. La mayoría de los scripts simples no requieren bash.
  4. El uso del shell POSIX es más portátil y los scripts se ejecutarán en una mayor variedad de sistemas.

17
Otra razón: a menudo / bin / sh es más rápido que bash, o al menos se carga más rápido (debido a que es más pequeño).
derobert

55
@derobert, /bin/shes más rápido si no es así bash, todavía hay algunos sistemas como OS / X o RHEL donde /bin/shestá bash.
Stéphane Chazelas

1
No. Algunos sistemas operativos lo vinculan, porque bash es compatible con versiones anteriores.
Sobrique

77
Un buen número de secuencias de comandos suponen que /bin/shes /bin/bash. El cambio de Ubuntu de bash a dash los rompió a todos.
atamanroman

19
@atamanroman: los scripts eran incorrectos en primer lugar, deberían haberlo usado #!/bin/bashsi quisieran Bash (¡no hay nada de malo en eso!). El cambio se realizó principalmente en sentido ascendente en Debian. Mejoró la experiencia del usuario, tuvo un impacto medible en el tiempo de inicio del sistema. También afectó positivamente la seguridad, ver "Shellshock".
Dietrich Epp

28

La mayoría de los scripts del sistema en Linux (relacionado con Debian: Ubuntu, Mint, etc.) están escritos para ejecutarse en el tablero más rápido, que es el valor predeterminado / bin / sh en esos sistemas. La razón es doble:

  • Velocidad del sistema. Un código más pequeño de tablero se carga más rápido y también se ejecuta más rápido. Con algún (¿pequeño?) Esfuerzo adicional (costo) para los programadores de scripts de shell.

  • Seguridad. Tener diversidad de conchas ayuda a la resistencia a los insectos. Los sistemas Debian en su mayoría no eran vulnerables al shellshock porque el shell predeterminado no tenía esa vulnerabilidad.

Bash es el shell predeterminado para los usuarios , ya que es más potente y tiene muchos más elementos para facilitar la codificación. También es el predeterminado shen Mac OS (el que está vinculado desde / bin / sh). Sin embargo, llamar bashcon el nombre del enlace shhace que comience como un shell compatible con posix.


2
Un conjunto más limitado de herramientas disponibles de un shell más simple hace que escribir código sea más difícil (evite cualquier guerra fanática sobre esto). Es por eso que a algunos usuarios les gusta zsh, que tiene incluso más herramientas disponibles que bash. Me gusta más Bash, ya que es un equilibrio entre ambos extremos.

44
@RobertL, muchas de las instalaciones agregadas en ksh y adoptadas por bash existen porque facilitan sustancialmente el proceso de escribir scripts sólidos y correctos. Sin las diversas adiciones que permiten que la asignación indirecta y la evaluación se realicen de manera segura, por ejemplo, uno puede encontrarse usando eval, con la exposición de seguridad correspondiente; Del mismo modo, sin soporte incorporado expresiones regulares, uno puede necesitar usar comandos externos (a una penalización de rendimiento pesado) para hacer coincidir incluso dentro de una sola línea, etc
Charles Duffy

1
@RuiFRibeiro, nada está estáticamente vinculado en Debian. El tablero es más limitado, pero está limitado principalmente en las características interactivas (sin finalización y demás), por lo que es más rápido para los scripts.
Jan Hudec el

21

Otros han señalado que las premisas de la pregunta, que el shell Bourne Again es predeterminado y omnipresente, son totalmente erróneas.

Además de eso, existen buenas razones para usar algo distinto del shell Bourne Again para interpretar los scripts del shell. Estas razones motivadas de Ubuntu y el gran proyecto de Debian, durante varios años, para eliminar del bash y hacer como muchos de los scripts de shell a cargo de la inicialización del sistema (que era una gran cantidad de secuencias de comandos shell con sistema 5 rc) y la instalación de paquetes / uso eliminación del Shell de Debian Almquist en lugar del shell Bourne Again.

En pocas palabras: el shell Bourne Again, repleto de características interactivas como es, no es el intérprete de shell más rápido para un script de shell compatible con POSIX. Entonces, si uno puede hacer que los scripts de shell sean compatibles con POSIX, interpretándolos con un programa más liviano, como el shell Debian Almquist, el sistema funcionará mejor. (Al final, Debian tuvo que hacer pequeños ajustes en el shell Almquist, para agregar soporte para un par de construcciones de shell que no son POSIX que simplemente estaban demasiado profundas y muy integradas y eran demasiado útiles para deshacerse de ellas).

El resultado de todo fue una gran ganancia en el rendimiento de arranque.

Entonces, hay dos clases distintas de shell para considerar, aquí:

  • Los shells con todas las características interactivas llamativas, que se configuran como shells de inicio de sesión interactivos para los usuarios en la base de datos de cuentas.
  • Los shells que interpretan muchos scripts rápidamente, que son utilizados como intérpretes de scripts por los programas de scripts de shell.

Tenga en cuenta que hablar de esto como "preferir /bin/sh" es simplificar demasiado. Debian en realidad tenía al menos dos objetivos:

  1. Frente a los administradores que utilizan el shell Debian Almquist, el shell Z (en modo POSIX), el shell Bourne Again (en modo POSIX), el shell MirBSD Korn y otros /bin/sh, ya que había ...

    1. ... haciendo que las secuencias de comandos sean lo más portátiles posible, de modo que cambiar lo /bin/shmapeado no rompa las cosas; o

    2. ... haciendo que los scripts no portátiles se dirijan explícitamente al programa de intérprete correcto , en lugar de simplemente esperar ese /bin/shmapa.

  2. Hacía que el shell Debian Almquist fuera el mapeo predeterminado para /bin/shBourne Shell, de modo que los scripts que eran compatibles con POSIX (o, más adecuadamente, conformes con el Manual de políticas de Debian) se ejecutaban más rápidamente.

Y, por supuesto, una vez que uno entra en esto, uno puede llevarlo mucho más lejos; como considerar las compensaciones de eficiencia de los gustos /bin/truey /usr/bin/clearser scripts de shell o programas compilados. Pero eso está más allá del alcance de esta respuesta, afortunadamente. ☺

Nada de esto es muy nuevo, ni siquiera específico de Unix, por supuesto. Volver antes de la vuelta del siglo, escribí y publiqué un intérprete de línea de comandos que se incluye en ambos y sabores "interactivos" "no interactivos", que explica precisamente esta división en su mana y tomando nota de la diferencia entre las COMSPECy OS2_SHELLvariables de entorno. Del mismo modo, la discusión sobre la eliminación de bashismos en el Sistema V de Debian rcy los scripts de instalación / eliminación de paquetes se remontan a la década de 1990.

Otras lecturas


2
"Al final, Debian tuvo que hacer pequeños ajustes en el shell de Almquist, para agregar soporte para un par de construcciones de shell no POSIX que simplemente estaban demasiado profundas y ampliamente integradas y eran demasiado útiles para deshacerse de ellas". - ¿Cuál de tus muchos enlaces tiene información sobre esto? Eso suena muy interesante. :)
Comodín el

3
En mi humilde opinión, el rendimiento es solo un motivador para lograr que las personas estén de acuerdo con los cambios. La gran razón inicial para cambiar fue que bash siguió rompiendo la compatibilidad con versiones anteriores. Personalmente, tuve que solucionar problemas de bash al menos 3 veces en mi carrera porque el script funcionaría en una versión de bash pero falló en otra (generalmente ocurre después de la actualización del sistema operativo). Dash no es simplemente un intérprete un poco más rápido. También es mucho más estable en términos de comportamiento.
slebetman

Me interesaría si los comentarios en la Schily Bourne Shellpágina de manual, ver schilytools.sourceforge.net/bosh.html son adecuados para permitir que las personas entiendan cómo escribir un script portátil (eso solo depende Bourne Shell featuresde 1989). Lo que hice fue mencionar todas las mejoras que no estaban en los viejos Bourne Shells. Por cierto: también estoy interesado en conocer una lista de bashisms en el tablero.
schily

8

¿Hay alguna razón para tener un shebang apuntando a / bin / sh en lugar de / bin / bash?

Si. La excelente respuesta de @ Marco lo describe bien.

¿Qué debo usar en mi shebang?

Al escribir sus propios guiones, debe señalar el shebang a la cosa más general que ha probado.

En mi sistema (Centos 6.6), shestá vinculado a bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Esto significa que siempre lo uso #!/bin/bashen mi shebang a menos que haya verificado que no tengo bashims en mi script.

Al configurar el shebang, #!/bin/shusted promete que el script funcionará con todas las implementaciones de sh.

Esta es una promesa mucho más grande que decir que el script funcionará con bash.

Aquí hay un ejemplo de un script que se comportará incorrectamente según la shimplementación que esté utilizando el sistema:

#!/bin/sh
n=1
a=$((++n))
echo $n

Al usar bashel script se imprimirá:

2

Al usar dashel script se imprimirá:

1

Si quiero usar, #!/bin/sh¿qué debo hacer?

  • Verifique el script con checkbashisms- Tenga en cuenta que esto no encontrará todos los bashims. No encontró el bashism en mi guión arriba
  • Pruebe el script usando otra shimplementación. Normalmente dashpruebo con , sin embargo, espero que algunos bashisms o dashims todavía puedan pasar.

La página DashAsBinSh en el wiki de Ubuntu tiene mucha información interesante.


66
"Al escribir sus propios scripts, debe señalar el shebang hacia lo más general que haya probado ... Al establecer el shebang en #! / Bin / sh, promete que el script funcionará con todas las implementaciones de sh ". Excelente punto +1, y me has hecho repensar cómo escribiré mis shebangs para el futuro. ¡Gracias! :)
Comodín el

2
Bueno, no todas las implementaciones de /bin/sh; solo los que cumplen con POSIX.
Blacklight Shining

4

La única razón restante para escribir un script de shell, en lugar de un script en un lenguaje más potente y ergonómico, es si la portabilidad a sistemas heredados con un conjunto desconocido de software instalado es más importante que cualquier otro factor .

/bin/shes el único intérprete de guiones que está disponible en todo lo que se llama a sí mismo Unix. Pero en una gran cantidad de sistemas heredados, /bin/shy las utilidades asociadas ni siquiera cumplen con la especificación POSIX.1-1996 "shell y utilidades", y mucho menos con algo más moderno. Las herramientas que cumplen con los estándares son un complemento opcional, instalado en /usr/xpg4alguna ubicación no obvia. 1 Las secuencias de comandos en el lenguaje de shell del subconjunto portátil son aún más tediosas y propensas a errores que las secuencias de comandos en el lenguaje de shell POSIX. (Lea un configurescript generado por Autoconf en algún momento si no me cree. Solo la configuración debería ser suficiente para convencerlo).

Pero si puede asumir que está instalado otro intérprete de script (por ejemplo, Bash), puede suponer que está instalado un intérprete para un mejor lenguaje de script . Perl, por ejemplo, es más probable que esté disponible que Bash.

Por lo tanto, nunca debe escribir un #! /bin/bashscript, porque si esa es una opción, un mejor idioma también es una opción.

1 Por ejemplo, Solaris 10 y anteriores enviaron el shell Bourne original como /bin/sh. Me informan que Solaris 11 lo actualizó a ksh93.


3
¿En qué idioma escribirás un script para iniciar un sistema? ¿O dentro de un enrutador SOHO (sistemas embebidos limitados)? ¿O en Android? Un shell estará disponible en todos esos casos. Perl no.

1
Hay algunas imprecisiones sobre las partes de su respuesta relacionadas con Solaris. En Solaris 10 y versiones anteriores, no/bin/sh es POSIX.1-1996, sino que en realidad es un shell Bourne original de sintaxis previa a POSIX. Eso hace un shebang muy pobre para que los scripts se ejecuten con estos lanzamientos. Se utilizarían scripts portátiles en Solaris que no serán muy portátiles en otros sistemas operativos. En el último Solaris, Oracle Solaris 11 lanzado por primera vez en 2011, es un moderno que cumple con las especificaciones POSIX recientes y tiene muchas extensiones modernas. #!/bin/sh#!/usr/xpg4/bin/sh/bin/shksh93
jlliagre

1
@BinaryZebra: "Un shell" estará disponible, sí. Pero bash no es necesariamente ese shell (en particular, la mayoría de los enrutadores SOHO usan el ashque se proporciona con busybox), y tiendo a pensar que zwol tiene razón en que perl está más comúnmente disponible que bash.
Ben Voigt

1
@BenVoigt Estoy comentando esta oración "La única razón restante para escribir un script de shell". Todavía hay algunas instancias que necesitan un shell para algunas tareas (no todas). Esos fueron algunos casos desde lo alto de mi cabeza. OTOH En sistemas con suficiente memoria (casi todos los estándares actuales) y suficiente potencia, instalar Perl (o Python, o ...) es bastante rápido y fácil. Sin embargo, no estoy abogando por ningún shell específico. ¿Dónde lees eso en mi comentario?

2
No está de acuerdo con su afirmación altamente objetiva y no objetiva de que "si bashestá disponible, entonces es un mejor idioma, por lo que nunca debe escribir ningún bashcódigo". Además, como señala @sixtyfootersdude, siempre debe usarlo a #!/bin/bashmenos que haya probado que su script funciona con cualquier shell POSIX.
Comodín el

0

En realidad deberías estar usando cualquiera

#! /bin/env sh

o

#! /bin/env bash

de esa manera invocas a cualquiera de los shell por la forma en que se instalan en ese sistema.

Para ser súper seguro ( por ejemplo, en casos de reinicios de un solo usuario), use de shotra manera bash.


66
De esta respuesta : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Esto probablemente también se aplica a shy bash.
Julio

12
No, no debe usar #!/bin/envnada en un script portátil. Es perfectamente razonable suponer que /bin/shexiste y que es un shell que funciona y cumple con POSIX. Por otro lado, ninguno de mis sistemas tiene un /bin/env.
Blacklight Shining

También un buen punto.
Jules

1
@Blacklight Shining definitivamente es un error asumir un shell compatible con POSIX /bin/sh. POSIX no lo requiere y define otras reglas para obtener un entorno compatible con POSIX en una plataforma certificada POSIX.
schily

44
/usr/bin/envno está universalmente disponible ...
vonbrand
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.