¿Por qué es echo un shell construido en comando?

34
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

¿Por qué no es eco de una utilidad independiente como ls, ps, catetc.? ¿Por qué es específico de shell? ¿Alguna buena razón?

Lazer
fuente
55
Tenga en cuenta que esto es específico del shell. ZSH lo incorpora, BASH no.
tsvallender
21
@tsv: echosin duda es un Bash incorporado. De hecho, es uno de los componentes principales más modernos.
Pausado hasta nuevo aviso.

Respuestas:

71

Hay dos clases de incorporados:

  1. Algunos comandos tienen que estar integrados en el programa shell porque no pueden funcionar si son externos.

    cdes uno de estos, ya que si fuera externo, solo podría cambiar su propio directorio; No podría afectar el directorio de trabajo actual del shell. (Ver también: ¿Por qué cdno es un programa? )

  2. La otra clase de comandos está integrada en el shell únicamente por eficiencia.

    La página de manual contiene una sección sobre órdenes internas que menciona , y como ejemplos de comandos en esta clase.dash printfechotest

Los sistemas Unix siempre han incluido ejecutables separados para comandos en esa segunda clase. Estos ejecutables separados todavía están disponibles en todos los sistemas Unixy que he usado, a pesar de que también están integrados en cada shell que es probable que use. ( POSIX realmente requiere que estos ejecutables estén presentes).

Creo que echose incorporó al shell en AT&T Unix System V Release 3.1. Lo baso en comparaciones de dos ediciones diferentes de manuales para sistemas Unix de la serie AT & Ts 3B1 . Alguien ha escaneado amablemente las ediciones de 1986 de estos manuales y los ha puesto en línea ; estos corresponden al lanzamiento original de SVR3. Puede ver que echono está en la lista en la página 523 del Manual del usuario de UNIX System V, Volumen II , donde lo esperaría si el comando se integrara en el shell. En mi copia local en papel de los manuales SVR3.1 de 1987, echo se enumera en esta sección del manual.

Estoy bastante seguro de que esta no es una innovación de Berkeley CSRG que AT&T trajo a casa. 4.3BSD salió el mismo año que SVR3, 1986, pero si mira la página de manual sh.1 de 4.3BSD , verá que echono está en la lista de comandos incorporados de la sección "Comandos especiales". Si CSRG hizo esto, eso nos deja queriendo una fuente documentada para probarlo.

En este punto, puede preguntarse si echose construyó en el shell antes de SVR3.1 y que este hecho simplemente no se documentó hasta entonces. El código fuente de AT&T Unix anterior a SVR3 más nuevo disponible para mí está en el tarball PDP-11 System III , en el que encontrará el código fuente de shell Bourne. No lo encontrará echoen la tabla de comandos integrada, que está en /usr/src/cmd/sh/msg.c. Según las marcas de tiempo en ese archivo, eso prueba que echociertamente no estaba en el shell en 1980.


Trivialidades

El mismo directorio también contiene un archivo llamado builtin.cque no contiene nada sobre el punto para esta pregunta, pero encontramos este comentario interesante:

/*      
    builtin commands are those that Bourne did not intend
    to be part of his shell.
    Redirection of i/o, or rather the lack of it, is still a
    problem..
*/      
Warren Young
fuente
En la página 385 de SysV UM, Vol II que mencionó, existe el printcomando incorporado para ksh que se dice que se comporta como echo. Este comando también está presente en algo como AT&T Unix SVR4 2.1 i386 de ISC. print "\012"produce el mismo resultado que haría eco. ¿Me pregunto por qué ksh tenía impreso y no echo incorporado? De todos modos realmente interesante.
¿Cuántas gemas de hace unos años se escabulleron esperando ser desenterradas por una edición en 2016? +1
iruvar
+1. Gracias. ¿Podría proporcionar las fuentes (referencias) con el propósito de hacer un comando integrado, para mi lectura / aprendizaje (sistemático)?
Tim
Quiero encontrar alguna referencia, manual o estándar para leer o aprender sistemáticamente. Traté de buscarlo en el manual de referencia de bash y las especificaciones POSIX. Pero no puedo encontrarlo. No estoy seguro si los extraño.
Tim
@Tim: Como esta y otras respuestas aquí explican, algunos comandos deben integrarse en el shell o no pueden hacer su trabajo. Todos los demás son puramente opcionales . Eso es esencialmente lo que mi fragmento de fuente de shell Bourne dice anteriormente, de hecho. Como construir tales comandos en el shell es opcional, una justificación autorizada solo podría dar la opinión de un implementador.
Warren Young
19

Hay una tercera razón para que algunos comandos se incorporen: se pueden usar cuando ejecutar comandos externos es imposible.

A veces, un sistema se rompe tanto que el lscomando no funciona. En algunos casos, un echo *seguirá funcionando.

Otro ejemplo (¡más importante!) Es kill: Si un sistema se queda sin PID libres, no es posible ejecutarlo /bin/kill(porque necesita un PID :-), pero el incorporado killfuncionará.

Por cierto, whiches un comando externo (al menos no es interno en bash), por lo que no puede enumerar los comandos internos. Por ejemplo:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo
bhm
fuente
No olvide que casi todos los ejecutables externos se basan en archivos de biblioteca. A veces ocurren catástrofes y esas bibliotecas no se pueden cargar (consejo: NUNCA emita a ldconfigmenos que sepa EXACTAMENTE lo que está haciendo). Además, ¿qué pasa si vuela su / bin, o peor aún, su partición / sbin, pero aún tiene un shell cargado?
LawrenceC
Si te quedas sin PID, puede ser difícil descubrir qué PID quieres matar. No puede ejecutar un pscomando, por lo que deberá buscar los PID manualmente /proc.
kasperd
Aunque en (al menos) CentOS whiches un alias bash que se ejecuta alias | /usr/bin/which --read-alias ...para que el externo which pueda identificar alias (pero aún no está integrado). No puedo decidir si considerar esto brillante o pervertido.
dave_thompson_085
En el punto en que el comando ls ya no funciona, creo que deberías montar el disco como esclavo en lugar de boot / master y arreglar la estructura de archivos de esa manera. No estoy seguro de cómo podría corregir ese grado de corrupción del sistema con echo a menos que sea echo> en un archivo y que tomaría mucho tiempo solucionarlo. De acuerdo, podrías escribir un script bash que fuera para arreglar la estructura del sistema.
jonnyjandles
13

De acuerdo con el Manual de referencia de Bash , se trata de conveniencia.

Los shells también proporcionan un pequeño conjunto de comandos integrados (incorporados) que implementan funcionalidades imposibles o inconvenientes de obtener a través de utilidades separadas. Por ejemplo, cd, break, continue y exec) no se pueden implementar fuera del shell porque manipulan directamente el shell. El historial, getopts, kill o pwd builtins, entre otros, podrían implementarse en utilidades separadas, pero son más convenientes de usar como comandos incorporados. Todas las conchas incorporadas se describen en secciones posteriores.

La Guía avanzada de secuencias de comandos Bash tiene una explicación más detallada:

"Una orden interna es una orden contenida dentro del conjunto de herramientas Bash, literalmente, construido en Esto es, ya sea por razones de rendimiento -. Builtins ejecutan más rápidamente que los comandos externos, que por lo general requieren que se bifurcan de 1 un proceso separado - o porque una orden interna del particular necesita directa acceso a los componentes internos del shell ".

También tenga en cuenta que echoexiste como una utilidad independiente en algunos sistemas. Esto es lo que tengo en mi sistema Darwin (MacOSX 10.5.8 - Leopard)

$ uname -a
Darwin host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo

echotambién está disponible como una versión incorporada, pero aparentemente mis scripts usan / bin / echo en mi Mac, y usan una versión Bash incorporada en la mayoría de mis sistemas Linux y FreeBSD. Pero eso no parece importar, porque las secuencias de comandos todavía funcionan bien en todas partes.

Stefan Lasiewski
fuente
3
Hablando de las funciones integradas de shell, debería usar "type" en lugar de "which".
Teddy
Gracias @ peluche. Empecé a hacer eso, cuando lo recuerdo. La vida es mucho mejor gracias a type.
Stefan Lasiewski
6

Para complementar la respuesta de bhm, digamos que /binse eliminó accidentalmente de su PATH. Te gustaría poder echo $PATHaveriguarlo, ¿verdad?

Daniel Hershcovich
fuente
2

Aunque la mayoría de los shells incluyen un incorporado echohoy en día, los CoreUtils de GNU también incluyen una implementación independiente del mismo:

$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo

Parece que no tiene GNU Coreutils instalado (la mayoría de los sistemas operativos de escritorio y servidor basados ​​en Linux lo tienen instalado de forma predeterminada, pero Linux incorporado u otro UNIX podrían usar colecciones alternativas de utilidades de shell en su lugar).

Por cierto: si miras Busybox , verás eso ls, psy cattambién hay comandos incorporados allí (o al menos puede ser; se usa para sistemas integrados y todo lo que no se necesita puede omitirse).

JanC
fuente
3
Las pruebas del póster original no respaldan la hipótesis que /bin/echono existe. Solo muestran que el incorporado tiene prioridad sobre cualquier echoprograma en la RUTA.
Warren Young
1

Aquí está la verdadera razón por la cual echodebería ser un shell incorporado:

Supongamos que tiene una contraseña $PASSWORD. ¿Cómo se escribe en un archivo ./password? Naturalmente, la mayoría de los programadores escribirían:

echo "$PASSWORD" >./password

Sin embargo, si echono fuera un shell incorporado, la contraseña se filtraría a todos los usuarios a través de la psinformación.

Por supuesto, si desea ser inteligente al respecto, puede encontrar una manera de almacenar una contraseña sin echo, quizás explotando alguna otra función de shell:

cat >./password <<EOF
${PASSWORD}
EOF

Sin embargo, tener echoun builtin incorporado es un cinturón de seguridad importante, ya que la forma más obvia de guardar una contraseña en un archivo también debería funcionar.

Daniel deprimido
fuente
3
Si bien es un efecto secundario útil, me parece muy dudoso que esa fuera la razón.
enchufe el
@DepressedDaniel: ¿Qué te respalda? ¿Dónde está la referencia que utilizó para respaldar su respuesta?
bromista