Розуміння команд, побудованих в оболонці


12

У посібнику з bash написано, що

Builtin commands are contained >>> within <<< the shell itself

Також у цій відповіді зазначено, що

A built-in command is simply a command that the shell carries out itself,
instead of interpreting it as a request to load and run some
>>> other program <<<

Коли я біг compgen -bна bash 4.4, я отримую список всіх оболонки вбудовані командами. Я бачу, наприклад, що [і killперераховані як оболонки. Але їх фактичні місця розташування:

/usr/bin/[
/bin/kill

Я думав, що бути builtinзасобом, що команда складається в /bin/bashвиконуваний файл. Отже, що насправді бентежить: Будь ласка, виправте мене, але як може бути окрема команда a builtin, коли вона насправді не є частиною оболонки?


1
Деякі команди спочатку існували як окремі утиліти. Зараз їх присутність відповідає стандарту POSIX, мобільності та мобільності. Оболонки реалізують деякі як вбудовані для продуктивності. Можливо, є й інша причина, але це про це без зайвих деталей.
Сергій Колодяжний

1
Ще одна причина, про яку я міг подумати, полягає в тому, що деякі вбудовані команди потрібні спеціально для оболонки, як execманіпулювання дескрипторами файлів та eval для оцінки команд. Вони не потрібні як окремі команди
Сергій Колодяжний

Відповіді:


16

Команди, вбудовані в оболонку, часто вбудовуються через збільшення продуктивності, яке це дає. Наприклад, виклик зовнішньої програми printf відбувається повільніше, ніж використання вбудованого printf.

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

Деякі вбудовані оболонки також надають розширення до зовнішньої еквівалентної команди. printfНаприклад, Баш вміє це робити

$ printf -v message 'Hello %s' "world"
$ echo "$message"
Hello world

(друк до змінної), яку зовнішня /usr/bin/printfпросто не змогла б зробити, оскільки вона не має доступу до змінних оболонок у поточному сеансі оболонки (і не може їх змінити).

Вбудовані утиліти також не мають обмеження, що їх розширений командний рядок повинен бути коротшим певної довжини. Робимо

printf '%s\n' *

Тому безпечно, якщо printfвбудована команда оболонки. Обмеження на довжину командного рядка походить від execve()функції бібліотеки С, яка використовується для виконання зовнішньої команди. Якщо командний рядок і поточне середовище більше, ніж ARG_MAXбайти (див. getconf ARG_MAXВ оболонці), виклик до execve()не вдасться. Якщо утиліта вбудована в оболонку, execve()викликати її не доведеться.

Вбудовані комунальні послуги мають перевагу над утилітами, знайденими в $PATH. Щоб відключити вбудовану команду bash, використовуйте напр

enable -n printf

Існує короткий список утиліт, які потрібно вбудувати в оболонку (взяті зі списку спеціальних вбудованих стандартів POSIX )

break
colon (:)
continue
dot (.)
eval
exec
exit
export
readonly
return
set
shift
times
trap
unset

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

Цікаво, що cdце не є частиною цього списку, але POSIX про це говорить наступне :

Оскільки cdвпливає на поточне середовище виконання оболонки, вона завжди надається як регулярна вбудована оболонка. Якщо він викликається в допоміжному або окремому середовищі виконання утиліти, наприклад, одному з наступних:

(cd /tmp)
nohup cd
find . -exec cd {} \;

це не впливає на робочий каталог оточення абонента.

Тому я припускаю, що "спеціальні" вбудовані модулі не можуть мати зовнішніх аналогів, тоді як cdтеоретично це може бути (але це не дуже зробить).


IIRC, chdir/ cdбули зовнішніми бінарними файлами в дуже ранніх Unices / перед Unix fork.
Xophmeister

@Xophmeister Solaris 11.4 (бета) все ще є /usr/bin/cd, але він фактично не змінить поточний робочий каталог. У посібнику сказано: /usr/bin/cdне впливає на процес виклику, але його можна використовувати для визначення того, чи може вказаний каталог бути встановлений як поточний каталог.
Кусалаланда

2
Ще одна досить конкретна причина вбудованих файлів: вбудований killтакож приємний тим, що не потрібно розщеплювати ще один процес, добре, якщо ви досягли обмеження кількості процесів.
дероберт

7

Вас (дуже зрозуміло) бентежить той факт, що деякі вбудовані існують і як вбудовані, і як зовнішні команди. Отже, хоча ви маєте рацію, що, наприклад, є /bin/[команда, це не означає, що в ній знаходиться "фактичне розташування" /bin.

Будь простий спосіб перевірити це запустити typeз -aвимикачем , який покаже всі доступні екземпляри команди. У моїй системі Arch це показує:

$ type -a [
[ is a shell builtin
[ is /sbin/[
[ is /usr/sbin/[
[ is /usr/bin/[

Зауважте, що /sbin, /usr/sbinі /binвсі посилання на них вказують /usr/bin, тому існує лише одна зовнішня [:

$ readlink -f /usr/sbin /sbin /bin/
/usr/bin
/usr/bin
/usr/bin

Як бачите, [це і вбудована, і зовнішня команда, і те саме стосується різних інших вбудованих оболонок. Однак це не змінює факту, що вони також є вбудованими оболонками, зібраними в саму оболонку.


чому distro. забезпечити окрему зовнішню команду для вже існуючої внутрішньої команди? чому вони дублюють?
LoveWithMaths

1
@linuxuser деякі з цих утиліт потрібні POSIX, і ви не можете знати, чи оболонка, якою користувач користується, також забезпечить вбудований модуль. Не вважайте їх внутрішніми командами ОС, вони є лише внутрішніми командами оболонки, і оболонка може змінюватися.
тердон

У мене зараз 1 сумнів, якщо внутрішні команди надаються оболонкою; то хто надає зовнішні команди? як я спостерігав багато команд, які доступні як внутрішні, так і зовнішні команди, але я мав явно встановити їх; так хто забезпечує зовнішнє командування? Distro забезпечує їх правильними?
LoveWithMaths

@linuxuser залежить від команди та операційної системи. Наприклад, на моєму Arch Linux, /bin/printfвстановлюється на coreutilsкорпусі і /bin/killна util-linux.
тердон

Мені шкода, але мені все одно незрозуміло, що з вищезазначеного надається distro? а що з іншим, який не надається дистрибутивом, тоді хто його забезпечує.
LoveWithMaths
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.