Чому в команді вбудована команда оболонки?


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

Чому луна не є незалежною утилітою , як ls, ps, і catт.д.? Чому вона специфічна для оболонки? Будь-які вагомі причини?


5
Майте на увазі, що це оболонка. ZSH вбудовує його, BASH - ні.
цваллендер

21
@tsv: echoзвичайно , це Bash вбудований. Насправді це вбудований у кожну велику сучасну оболонку.
Призупинено до подальшого повідомлення.

Відповіді:


71

Існує два класи вбудованих:

  1. Деякі команди повинні бути вбудовані в програму оболонки, оскільки вони не можуть працювати, якщо вони зовнішні.

    cdє одним з таких, оскільки якби він був зовнішнім, він міг би змінити лише власний каталог; це не могло вплинути на поточний робочий каталог оболонки. (Див. Також: Чому це cdне програма? )

  2. Інший клас команд вбудований в оболонку виключно для ефективності.

    Сторінка людей має розділ вбудованих команд , в якому згадується , і в якості прикладів команд в цьому класі.dash printfechotest

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

Я вважаю, що echoвін вбудований в оболонку в AT&T Unix System V Випуск 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, але якщо ви подивитесь на сторінку 1 -ї shBS 4.3BSD , ви побачите, що echoїї немає в списку вбудованих команд розділу "Спеціальні команди". Якщо CSRG це зробив, це залишає нас бажати документально підтвердженого джерела.

На даний момент ви можете задуматися, чи echoвбудований він в оболонку раніше, ніж SVR3.1, і що цей факт просто не був задокументований до цього часу. Найновіший доступний для мене вихідний код pred-SVR3 AT&T Unix знаходиться у PDP-11 System III tarball , де ви знайдете вихідний код оболонки 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, Vol II, є вбудована printкоманда для ksh, яка, як кажуть, поводиться так echo. Ця команда також присутня у чомусь на зразок AT&T Unix SVR4 2.1 i386 від ISC. print "\012"дає такий же результат, як і відлуння. Цікаво, чому ksh мав друк, а не вбудований ехо? У будь-якому разі справді цікаво.

Скільки таких дорогоцінних каменів за кілька років тому викрали в очікуванні, щоб їх розкопали в редакції в 2016 році? +1
ірувар

+1. Спасибі. Чи можете ви надати джерела (посилання) для створення команди, вбудованої для мого (систематичного) читання / навчання?
Тим

Я хочу знайти якийсь довідник, посібник чи стандарт для систематичного читання чи навчання. Я намагався знайти це у посібнику bash та специфікаціях POSIX. Але я не можу його знайти. Я не впевнений, чи сумую за ними.
Тім

@Tim: Як пояснюють цей та інші відповіді тут, деякі команди повинні бути вбудовані в оболонку, або вони не можуть виконувати свою роботу. Усі інші суто необов’язкові . Це фактично те, що мій фрагмент джерела оболонки Борна говорить вище, насправді. Оскільки введення таких команд у оболонку необов’язкове, авторитетне обгрунтування може дати лише одну думку виконавця.
Warren Young

19

Існує третя причина вбудованості деяких команд: їх можна використовувати, коли виконання зовнішніх команд неможливо.

Іноді система стає настільки зламаною, що lsкоманда не працює. У деяких випадках echo *заповіт все ще спрацює.

Ще один (важливіший!) Приклад kill: Якщо в системі не вистачає безкоштовних PID, запустити /bin/killїї неможливо (тому що їй потрібен PID :-), але вбудований killбуде працювати.

Btw., whichЄ зовнішньою командою (принаймні вона не є внутрішньою в bash), тому вона не може перелічити внутрішні команди. Наприклад:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo

Не забувайте, що майже всі зовнішні виконувані файли покладаються на бібліотечні файли. Іноді трапляються катастрофи, і ці бібліотеки неможливо завантажити (порада: НІКОЛИ не видавати, ldconfigякщо ви точно не знаєте, що ви робите). Крім того, що робити, якщо ви підірвете ваш / bin або, що ще гірше, свій / sbin розділ, але все ще завантажений оболонку?
LawrenceC

Якщо у вас не вистачає PID, важко дізнатися, який саме PID ви хочете вбити. Ви не можете запустити psкоманду, тому вам доведеться знаходити PID вручну /proc.
kasperd

Хоча на (принаймні) CentOS whichє баш-псевдонім, який працює, alias | /usr/bin/which --read-alias ...тому зовнішній which може ідентифікувати псевдоніми (але все ще не вбудовані). Я не можу вирішити, чи вважати це геніальним чи збоченим.
dave_thompson_085

Після того, як команда ls більше не працює, я думаю, що ви повинні встановлювати диск як підлеглий, а не завантажувач / master та фіксувати файлову структуру таким чином. Я не впевнений, як ви могли виправити таку ступінь пошкодження системи за допомогою ехо, якщо ви не знайдете ехо> у файл, і це потребує довгого виправлення. Звичайно, ви можете написати скрипт bash, який повинен був виправити структуру системи.
jonnyjandles

13

Згідно довідкового керівництва Bash , мова йде про зручність.

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

Посібник з розширеного сценарію Bash має більш детальне пояснення:

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

Також зауважте, що echoв деяких системах існує як окрема утиліта. Ось що я маю в моїй системі Дарвіна (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" замість "what".
Тедді

Дякую @Teddy. Я почав це робити, коли згадую. Життя набагато краще завдяки 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 можуть використовувати альтернативні колекції утиліт оболонок).

BTW: якщо ви подивитесь на Busybox , ви побачите це ls, psа catтакож є вбудованими командами там (або, принаймні, можна; він використовується для вбудованих систем, і все необхідне може бути залишене).


3
Тести оригінального плаката не підтверджують гіпотезу, що /bin/echoне існує. Вони просто показують, що вбудований має перевагу над будь-якою echoпрограмою PATH.
Warren Young

1

Ось справжня причина, чому echoмає бути вбудована оболонка:

Припустимо, у вас пароль $PASSWORD. Як записати його у файл ./password? Природно, що більшість програмістів написали б:

echo "$PASSWORD" >./password

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

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

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

Однак наявність echoвбудованої системи є важливим ременем безпеки, оскільки найочевидніший спосіб збереження пароля у файлі також повинен працювати.


3
Хоча корисний побічний ефект, я вважаю, що це дуже сумнівно, що це було причиною.
підключення

@DepressDaniel: Що створює резервну копію? Де посилання, яке ви використовували для підтримки своєї відповіді?
жартівник
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.