Почему echo является оболочкой, встроенной в команду?

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

Почему эхо не является независимой утилитой , как ls, ps, и catт.д.? Почему это специфическая оболочка? Есть веские причины?

Lazer
источник
5
Имейте в виду, что это зависит от оболочки. ZSH встраивает его, BASH - нет.
Цваллендер
21
@tsv: echoбезусловно , это является встроенной Bash. На самом деле, это встроенный в каждую большую современную оболочку.
Приостановлено до дальнейшего уведомления.

Ответы:

71

Существует два класса встроенных функций:

  1. Некоторые команды должны быть встроены в саму программу оболочки, потому что они не могут работать, если они являются внешними.

    cdявляется одним из таких, поскольку, если бы он был внешним, он мог бы изменить только свой собственный каталог; это не могло повлиять на текущий рабочий каталог оболочки. (Смотрите также: Почему это cdне программа? )

  2. Другой класс команд встроен в оболочку исключительно для эффективности.

    Страница людей имеет раздел встроенных команд , в котором упоминается , и в качестве примеров команд в этом классе.dash printfechotest

Системы Unix всегда включали отдельные исполняемые файлы для команд этого второго класса. Эти отдельные исполняемые файлы все еще доступны в каждой системе Unixy, которую я использовал, хотя они также встроены в каждую оболочку, которую вы, вероятно, будете использовать. ( POSIX фактически требует наличия этих исполняемых файлов.)

Я считаю, echoчто встроен в оболочку в AT & T Unix System V Release 3.1. Я основываюсь на сравнении двух разных изданий руководств для систем Unix серии AT & Ts 3B1 . Кто-то любезно отсканировал издания этих руководств 1986 года и разместил их в Интернете ; они соответствуют оригинальной версии SVR3. Вы можете видеть, что этого echoнет в списке на странице 523 Руководства пользователя UNIX System V, том II , где вы ожидаете этого, если команда встроена в оболочку. В моей местной бумажной копии SVR3.1 пособий с 1987 года, echo находится в списке в этом разделе руководства.

Я почти уверен, что это не инновация Berkeley CSRG, которую AT & T вернула домой. 4.3BSD вышла в том же году, что и SVR3, 1986, но если вы посмотрите на man-страницу 4.3BSD sh.1 , вы увидите, что echoее нет в списке встроенных команд раздела «Специальные команды». Если CSRG сделает это, то мы будем нуждаться в документированном источнике, чтобы это доказать.

В этот момент вы можете задаться вопросом, echoбыл ли он встроен в оболочку раньше, чем SVR3.1, и что этот факт просто не был задокументирован до этого момента. Новейший исходный код Unix для AT & T до SVR3, доступный мне, находится в архиве PDP-11 System III , в котором вы найдете исходный код оболочки Bourne. Вы не найдете echoв встроенной таблице команд, которая находится в /usr/src/cmd/sh/msg.c. Судя по меткам времени в этом файле, это доказывает, что echoв 1980 году его точно не было в оболочке.


пустяки

В том же каталоге также содержится файл с именем, builtin.cкоторый не содержит ничего для этого вопроса, но мы находим этот интересный комментарий:

/*      
    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..
*/      
Уоррен Янг
источник
На странице 385 SysV UM, том II, о котором вы упоминали, есть встроенная printкоманда для ksh, которая, как говорят, ведет себя как echo. Эта команда также присутствует в чем-то вроде AT & T Unix SVR4 2.1 i386 от ISC. print "\012"дает тот же результат, что и эхо. Интересно, почему у ksh был print, а не echo встроенный? В любом случае действительно интересно.
Сколько таких драгоценных камней за несколько лет назад было убрано в ожидании, чтобы быть найденным в 2016 году? +1
ирувар
+1. Спасибо. Не могли бы вы предоставить источники (ссылки) для создания встроенной команды, для моего (систематического) чтения / обучения?
Тим
Я хочу найти справочник, руководство или стандарт для систематического чтения или изучения. Я попытался найти его в справочном руководстве bash и в спецификациях POSIX. Но я не могу найти это. Я не уверен, что скучаю по ним.
Тим
@Tim: Как объясняют этот и другие ответы, некоторые команды должны быть встроены в оболочку, иначе они не смогут выполнять свою работу. Все остальные сугубо необязательны . По сути, это то, что мой фрагмент исходного кода Bourne говорит выше, на самом деле. Поскольку встраивание таких команд в оболочку является необязательным, авторитетное обоснование может дать мнение только одного разработчика.
Уоррен Янг
19

Существует третья причина, по которой некоторые команды должны быть встроены: их можно использовать, когда выполнение внешних команд невозможно.

Иногда система становится настолько сломанной, что lsкоманда не работает. В некоторых случаях, по- echo *прежнему будет работать.

Другой (более важный!) Пример kill: если в системе заканчиваются свободные идентификаторы PID, запуск невозможен /bin/kill(потому что для этого требуется идентификатор PID :-), но встроенная система killбудет работать.

Кстати, whichэто внешняя команда (по крайней мере, она не является внутренней в bash), поэтому она не может перечислить внутренние команды. Например:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo
BHM
источник
Не забывайте, что почти все внешние исполняемые файлы используют библиотечные файлы. Иногда случаются катастрофы, и эти библиотеки не могут быть загружены (совет: НИКОГДА ldconfigне выпускайте, если вы точно не знаете, что делаете). Кроме того, что если вы удалите ваш / bin или, что еще хуже, раздел / sbin, но все равно загрузите оболочку?
LawrenceC
Если у вас закончились PID, может быть трудно определить, какой PID вы хотите убить. Вы не можете выполнить psкоманду, поэтому вам придется вручную найти PID /proc.
Касперд
Хотя на (по крайней мере) CentOS whichявляется псевдонимом bash, который работает alias | /usr/bin/which --read-alias ...так, что внешние which могут идентифицировать псевдонимы (но все же не встроенные). Я не могу решить, считать это гениальным или извращенным.
dave_thompson_085
В тот момент, когда команда ls больше не работает, я думаю, что вы должны монтировать диск как slave вместо boot / master и фиксировать файловую структуру таким образом. Я не уверен, как вы могли бы исправить такую ​​степень повреждения системы с помощью echo, если вы не вставили echo> в файл, и это заняло бы много времени. Конечно, вы можете написать bash-скрипт, который должен был исправить структуру системы.
jonnyjandles
13

Согласно справочнику Bash , речь идет об удобстве.

Оболочки также предоставляют небольшой набор встроенных команд (встроенных функций), реализующих функциональные возможности, которые невозможно или неудобно получить с помощью отдельных утилит. Например, cd, break, continue и exec) не могут быть реализованы вне оболочки, потому что они напрямую манипулируют самой оболочкой. Встроенные функции history, getopts, kill или pwd, среди прочего, могут быть реализованы в отдельных утилитах, но их удобнее использовать в качестве встроенных команд. Все встроенные функции оболочки описаны в последующих разделах.

Scripting Guide Advanced Bash имеет более подробное объяснение:

«Встроенная команда - это команда, содержащаяся в наборе инструментов Bash, в буквальном смысле слова встроенная. Это либо из соображений производительности - встроенные команды выполняются быстрее, чем внешние команды, для которых обычно требуется отключить 1 отдельный процесс - или потому что конкретная встроенная система требует прямого доступ к внутренностям оболочки ".

Также обратите внимание, что echoв некоторых системах она существует как отдельная утилита. Вот что у меня есть в моей системе 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также доступен как встроенный, но, очевидно, мои скрипты используют / bin / echo на моем Mac и используют встроенный Bash на большинстве моих систем Linux и FreeBSD. Но это, похоже, не имеет значения, потому что сценарии по-прежнему работают хорошо везде.

Стефан Ласевский
источник
3
Говоря о встроенных оболочках, вы должны использовать «тип» вместо «который».
Тедди
Спасибо, Тедди. Я начал делать это, когда я помню. Жизнь намного лучше благодаря type.
Стефан Ласевский
6

Чтобы дополнить ответ bhm, допустим, он /binбыл случайно удален из вашего PATH. Вы бы хотели echo $PATHэто выяснить, верно?

Даниил Гершкович
источник
2

Несмотря на то, что большинство оболочек в echoнастоящее время включают встроенные средства , GNU CoreUtils также включает в себя отдельную реализацию:

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

Похоже, у вас не установлена ​​GNU Coreutils (большинство ОС для настольных ПК и серверов на основе Linux устанавливают ее по умолчанию, но встроенный linux или другой UNIX могут использовать вместо этого альтернативные наборы утилит оболочки).

Кстати: если вы посмотрите на Busybox , вы увидите это ls, psа catтакже там есть встроенные команды (или, по крайней мере, они могут быть; они используются для встроенных систем, и все ненужное может быть опущено).

Janc
источник
3
Тесты оригинального плаката не поддерживают гипотезу, /bin/echoкоторая не существует. Они просто показывают, что встроенное имеет приоритет над любой echoпрограммой в PATH.
Уоррен Янг
1

Вот настоящая причина, почему echoдолжна быть встроенная оболочка:

Предположим, у вас есть пароль $PASSWORD. Как вы пишете это в файл ./password? Естественно, большинство программистов написали бы:

echo "$PASSWORD" >./password

Однако, если бы echoне встроенная оболочка, пароль передавался бы всем пользователям через psинформацию.

Конечно, если вы хотите проявить смекалку, вы можете найти способ сохранить пароль без использования echo, возможно, другой функции оболочки:

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

Однако наличие echoвстроенного является важным ремнем безопасности, так как наиболее очевидный способ сохранить пароль в файл также должен работать.

DepressedDaniel
источник
3
В то время как полезный побочный эффект я нахожу весьма сомнительным, что это было причиной.
plugwash
@DepressedDaniel: что тебя поддерживает? Где ссылка, которую вы использовали, чтобы поддержать свой ответ?
Джокер