$ which echo
echo: Shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat
¿Por qué echo no es una utilidad independiente como ls
, ps
, cat
etc? ¿Por qué es específico de Shell? ¿Alguna buena razón?
Hay dos clases de elementos integrados:
Algunos comandos deben estar integrados en el propio programa Shell porque no pueden funcionar si son externos.
cd
es uno de ellos, 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é cd
no es un programa? )
La otra clase de comandos está integrada en el Shell puramente por eficiencia.
El dash
página de manual tiene una sección sobre elementos integrados que menciona printf
, echo
y test
como ejemplos de comandos en esta clase.
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, aunque también están integrados en todos los Shell que probablemente uses. ( POSIX en realidad requiere que estos ejecutables estén presentes).
Creo que echo
se incorporó al Shell en AT&T Unix System V Release 3.1. Lo baso en comparaciones de dos ediciones diferentes de manuales para AT & Ts sistemas Unix de la serie 3B1 . Alguien ha escaneado amablemente las ediciones de 1986 de estos manuales y póngalos en línea ; estos corresponden a la versión original de SVR3. Puede ver que echo
no está en la lista de la página 523 de Manual del usuario de UNIX System V, Volumen II , donde lo esperaría si el comando estuviera integrado en el Shell. En mi copia impresa local de los manuales SVR3.1 de 1987, echo
aparece en esta sección del manual.
Estoy bastante seguro de que esto 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 observa página de manual sh.1 de 4.3BSD , verá que echo
no está en la lista de la sección "Comandos especiales" de comandos integrados. Si CSRG hizo esto, eso nos deja con ganas de una fuente documentada para probarlo.
En este punto, puede preguntarse si echo
fue integrado en el Shell antes que SVR3.1 y que este hecho simplemente no documentado hasta entonces. El código fuente Unix de AT&T anterior a SVR3 más reciente disponible para mí está en PDP-11 System III tarball , donde encontrará el código fuente de Bourne Shell. No encontrará echo
en la tabla de comandos incorporada, que está en /usr/src/cmd/sh/msg.c
. Basado en las marcas de tiempo en ese archivo, eso prueba que echo
ciertamente no estaba en el Shell en 1980.
El mismo directorio también contiene un archivo llamado builtin.c
que no contiene nada específico 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..
*/
Hay una tercera razón para que algunos comandos estén integrados: se pueden usar cuando es imposible ejecutar comandos externos.
A veces, un sistema se estropea tanto que el comando ls
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 ejecutar /bin/kill
(porque necesita un PID :-), pero el kill
incorporado funcionará.
Por cierto, which
es 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
De acuerdo con Bash Reference Manual , se trata de conveniencia.
Los shells también proporcionan un pequeño conjunto de comandos integrados (incorporados) que implementan una funcionalidad imposible o inconveniente de obtener mediante utilidades independientes. Por ejemplo, cd, break, continue y exec) no se pueden implementar fuera del Shell porque manipulan directamente el propio Shell. Los archivos internos history, getopts, kill o pwd, entre otros, podrían implementarse en utilidades separadas, pero son más convenientes de usar como comandos integrados. Todas las incorporaciones de Shell se describen en las secciones siguientes.
La Advanced Bash Scripting Guide tiene una explicación más detallada:
"Un builtin es un comando contenido dentro del conjunto de herramientas Bash, literalmente integrado. Esto es por razones de rendimiento: los internos se ejecutan más rápido que los comandos externos, que generalmente requieren bifurcación 1 un proceso separado - o porque un incorporado en particular necesita acceso directo al interior de Shell ".
También tenga en cuenta que echo
existe 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
echo
también está disponible como incorporado, pero aparentemente mis scripts usan/bin/echo en mi Mac, y usan un Bash incorporado en la mayoría de mis sistemas Linux y FreeBSD. Pero eso no parece importar, porque los scripts aún funcionan bien en todas partes.
Para complementar la respuesta de bhm, digamos /bin
se eliminó accidentalmente de su PATH
. Le gustaría poder echo $PATH
para averiguarlo, ¿verdad?
Aunque la mayoría de los shells incluyen un echo
incorporado hoy en día, los GNU CoreUtils 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 servidor y escritorio basados en Linux lo tienen instalado de forma predeterminada, pero Linux embebido u otro UNIX podría usar colecciones alternativas de utilidades de Shell en su lugar)) .
Por cierto: si miras Busybox , verás que ls
, ps
y cat
también son comandos integrados allí (o en menos puede ser; se usa para sistemas embebidos y todo lo que no se necesita puede omitirse).
Esta es la verdadera razón por la que echo
debería ser una función incorporada de Shell:
Suponga que tiene una contraseña en $PASSWORD
. ¿Cómo se escribe en un archivo ./password
? Naturalmente, la mayoría de los programadores escribirían:
echo "$PASSWORD" >./password
Sin embargo, si echo
no fuera un Shell incorporado, la contraseña se filtraría a todos los usuarios a través de la información de ps
.
Por supuesto, si quiere ser inteligente al respecto, puede encontrar una manera de almacenar una contraseña sin echo
, quizás explotando alguna otra característica de Shell:
cat >./password <<EOF
${PASSWORD}
EOF
Sin embargo, tener echo
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.