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

chevallier 05/10/2018. 2 answers, 817 views
bash shell shell-builtin

У бас-посібнику написано це

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 на compgen -b bash 4.4 , я отримую список всіх команд, що входять до складу оболонки. Я бачу, наприклад, що [ і kill , перераховані, щоб бути оболонкою вбудованих. Але їхні фактичні місця розташування:

/usr/bin/[
/bin/kill 

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

2 Answers


Kusalananda 05/10/2018.

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

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

Деякі вбудовані оболонки також надають розширення зовнішньої еквівалентної команди. Приклад Bash's, наприклад, здатний зробити

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

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

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

printf '%s\n' * 

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

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

enable -n printf 

Існує короткий список утиліт, які need вбудувати в оболонку (взяті зі списку спеціальних вбудованих стандартів 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 {} \; 

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

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


terdon 05/10/2018.

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

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

$ 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 

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

Related questions

Hot questions

Language

Popular Tags