$ 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
, cat
etc.? ¿Por qué es específico de shell? ¿Alguna buena razón?
fuente
$ 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
, cat
etc.? ¿Por qué es específico de shell? ¿Alguna buena razón?
Hay dos clases de incorporados:
Algunos comandos tienen que estar integrados en el programa shell porque no pueden funcionar si son externos.
cd
es 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é cd
no es un programa? )
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
printf
echo
test
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 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 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 echo
no 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 echo
no 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 echo
se 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á echo
en 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 echo
ciertamente no estaba en el shell en 1980.
El mismo directorio también contiene un archivo llamado builtin.c
que 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..
*/
print
comando 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.
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 ls
comando 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 kill
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
ldconfig
menos 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?
ps
comando, por lo que deberá buscar los PID manualmente /proc
.
which
es 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.
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 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 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.
type
.
Para complementar la respuesta de bhm, digamos que /bin
se eliminó accidentalmente de su PATH
. Te gustaría poder echo $PATH
averiguarlo, ¿verdad?
Aunque la mayoría de los shells incluyen un incorporado echo
hoy 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
, ps
y cat
también hay comandos incorporados allí (o al menos puede ser; se usa para sistemas integrados y todo lo que no se necesita puede omitirse).
/bin/echo
no existe. Solo muestran que el incorporado tiene prioridad sobre cualquier echo
programa en la RUTA.
Aquí está la verdadera razón por la cual echo
deberí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 echo
no fuera un shell incorporado, la contraseña se filtraría a todos los usuarios a través de la ps
informació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 echo
un 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.
echo
sin duda es un Bash incorporado. De hecho, es uno de los componentes principales más modernos.