Чому обов'язкові утиліти POSIX не вбудовані в оболонку?


45

Мета цього питання - відповісти на цікавість, а не на вирішення конкретної обчислювальної проблеми. Питання полягає в тому, чому обов'язкові утиліти POSIX зазвичай не вбудовуються в реалізацію оболонки?

Наприклад, у мене є сценарій, який в основному зчитує кілька невеликих текстових файлів і перевіряє, чи вони належним чином відформатовані, але на моїй машині працює 27 секунд через значну кількість маніпуляцій з рядками. Ця струнна маніпуляція створює тисячі нових процесів, викликаючи різні утиліти, звідси повільність. Я досить впевнений , що якщо деякі утиліти були побудовані, а саме grep, sed, cut, tr, і expr, то скрипт буде працювати в секунду або менше ( на основі мого досвіду в C).

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

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


15
Якщо 27 секунд занадто повільно, ви можете використовувати Python, Perl або якусь іншу напівкомпільовану мову. Крім того, розмістіть повільні частини сценарію та попросіть удосконалення. Можливо, ви використовуєте три-чотири команди, де можна зробити одну (більш швидку).
roaima

8
Оболонки насправді не були зроблені для важких завдань, на жаль, і світ сильно змінився з тих часів, коли ви могли піти з просто сценарієм оболонки. Я погоджуюся з roaima - кожен розумний sysadmin повинен їхати на Python або Perl і не сподіватися, що оболонка впорається з усім
Сергій Колодяжний

16
Основна мета оболонки - запуск інших програм, а не маніпулювання даними безпосередньо. Протягом багатьох років деякі зовнішні програми або функції, що надаються ними (глобулінг, арифметика printfтощо), були включені в оболонки, коли вони вважалися достатньо корисними.
чепнер

8
Якщо ви опублікуєте свій скрипт на codereview.stackexchange.com, я впевнений, що рецензенти можуть зробити кілька пропозицій, щоб швидко прискорити ваш сценарій (або принаймні вказати, чому він повинен бути написаний на Python / тощо замість оболонки).
чепнер

5
@Kyle: awkобов'язкова утиліта в POSIX, і особливо добре підходить (тобто, дуже швидко) для реалізації сценаріїв , які ви могли б реалізувати з допомогою sed, cut, tr, grepі exprв сценарії оболонки.
Номінальна тварина

Відповіді:


11

Не передбачається, що сценарії оболонки будуть працювати з таким типом швидкості. Якщо ви хочете покращити швидкість свого сценарію, спробуйте його в перл. Якщо це все ще занадто повільно, вам доведеться перейти до статично набраної мови, наприклад java або c, або написати модуль C для perl, який виконує надто повільні частини.

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

Очікується, що в Unix OS буде включено багато невеликих програм, які виконують чітко визначені завдання, що створюють більшу картину. Це гарна річ, оскільки вона розділяє більші програми. Погляньте, наприклад, на qmail та порівняйте його з sendmail. qmail складається з багатьох програм:

http://www.nrg4u.com/qmail/the-big-qmail-picture-103-p1.gif

Експлуатація мережевого демона не допоможе вам використовувати менеджера черг.


ОП спеціально НЕ просила пропозицій щодо підвищення швидкості коду. Питання полягало в тому, чому певні утиліти не вбудовані, як cdабо pwd.
Stephen C

4
Правда. Відповідь полягала в тому, щоб виразити різницю між монолітним та компартменталізованим та показати причину в цій користі.
Ед Невілл

Пов’язано: askubuntu.com/a/291926/11751
CVn

1
@StephenC cdє вбудованим - і це насправді повинно бути, оскільки зміна робочого каталогу в підпроцесі не впливає на батьківські процеси.
Йонас

67

Чому POSIX обов'язкові утиліти не вбудовані в оболонку?

Тому що бути POSIX - сумісної, система буде необхідно 1 , щоб забезпечити більшість утиліта як команди автономними.

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

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

Слід також зазначити , що , по крайней мере ksh93, bashі zshйти далі, надаючи спеціальні методи для запущеної командної оболонки для вбудованих команд навантаження динамічно з поділюваних бібліотек. Технічно ніщо тоді не заважає всім утилітам POSIX реалізовуватися та бути доступними як вбудовані.

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

1 POSIX.1-2008

Однак усі стандартні утиліти , включаючи звичайні вбудовані в таблицю, але не спеціальні вбудовані програми, описані в Спеціальних вбудованих утилітах, повинні бути реалізовані таким чином, щоб отримати доступ до них через сімейство exec функцій , визначених в томі системних інтерфейсів POSIX.1-2008, і їх можна викликати безпосередньо тими утилітами, які цього вимагають (env, find, nice, nohup, time, xargs).


4
Це правильна відповідь, але я просто додам, що оскільки інтерфейс цих утиліт, як правило, здійснюється через stdin / stdout, що навіть якщо кожна з них також була реалізована як вбудована програма в bash, вона фактично все ще потребуватиме все-таки розщедритися і створити труби для кожної команди в конвеєрі, так що буде лише незначний приріст
Чунко

2
@Chunko Так. проте, корпуси легші, ніж процеси fork / exec'ed.
jlliagre

3
@slebetman Ви пропустили мою думку. Абонементи не є ні потоками, ні виконаними процесами, незалежно від того, працюють вони в Linux чи ні. Абонементи - це лише їхній батьківський клон, створений fork не слідуючим exec; forkв даний час дуже легка операція порівняно з exec.
jlliagre

3
Я оцінив, що noforkвбудовані зайняті ящики мають на 10 разів менше накладних витрат, ніж noexecвбудовані, що, в свою чергу, на ~ 5 разів менше накладних витрат, ніж fork + exec окремого двійкового файлу. Визначення відповідно до unix.stackexchange.com/a/274322/29483 Цікаво, що у busbox не noforkвсе, хоча я знаю, що код зайнятої команди скорочується не очищенням пам'яті, а просто покладається на нетривалий процес.
sourcejedi

1
@jlliagre: На Linux Linux fork створює процес. Те, що вам, мабуть, не вистачає, полягає в тому, що в Linux вони настільки оптимізували процеси, що розробники визначили, що немає додаткової переваги, створюючи щось більш легке. В основному, в linux процес настільки ж легкий, як і потік.
slebetman

9

З посібника BASH ,

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

Як я впевнений, ви чули, філософія UNIX значною мірою покладається на кілька додатків, які мають обмежений функціонал. Кожен вбудований має дуже вагому причину, чому він вбудований. Все інше - ні. Я думаю, що більш цікавий клас питань уздовж ліній, «чому саме це pwd вбудований?»


2
Одним словом: Модульність
Пешке

2
/ bin / pwd існує. Я думаю, що тут cdбув би кращий приклад того, що неможливо реалізувати як окремий інструмент.
Оскар скаго

1
@OskarSkog У цьому справа. cdмає бути вбудований, pwdні. То чому ж bashвиконавці вирішили включити його?
Стиг Хеммер

1
... яка охоплена землею Unix.stackexchange.com/questions/145479 .
JdeBP

@StigHemmer /bin/bashіснує, але він все ще є вбудованим. Перегляньте список вбудованих файлів
Stephen C

8

Хлопці з AT&T запитали себе те саме

Якщо ви подивитесь на історію інструментарію програмного забезпечення AT&T (на даний момент лежить у стані спокою на github з моменту виходу основної команди), це саме те, що вони зробили зі шкаралупою AT&T Korn, aka ksh93.

Продуктивність завжди була частиною мотивації для підтримуючих служб ksh93, і при створенні ksh ви можете створити багато загальних утиліт POSIX як динамічно завантажених бібліотек. Прив’язуючи ці команди до імені каталогу, наприклад /opt/ast/bin, ви можете керувати, яка версія команди буде використовуватися, виходячи з позиції цього імені каталогу в $PATH.

Приклади:

cat chmod chown cksum cmp cp cut date expr fmt head join ln
mkdir mkfifo mktemp mv nl od paste rm tail tr uniq uuencode wc

Повний список можна знайти в сховищі github ast .

Зауважте, що більшість інструментів ast мають власне походження і сильно відрізняються від більш поширених програм для gnu. Дослідницька команда AT&T дотримувалася офіційних стандартів, що було способом досягти сумісності, коли ви не могли поділитися кодом.


6

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

POSIX визначає досить про утиліти, що, мабуть, не так вже й багато проблем мати різні реалізації.

це неправильне припущення :-P.

Системи Post-POSIX продовжують ставати більш потужними та зручними з поважних причин; як стандарт фактичного факту він ніколи насправді не наздоганяє.

Ubuntu розпочав зусилля, щоб перейти на зніману оболонку POSIX для сценаріїв, щоб оптимізувати старий процес завантаження системи V V. Я не кажу, що це не вдалося, але це спровокувало багато помилок, які довелося очистити: "башизми", сценарії, до яких запускалися /bin/sh, припускаючи, що bashфункції доступні.

POSIX sh не є хорошою мовою програмування загального призначення. Його головне призначення - добре працювати як інтерактивна оболонка. Як тільки ви почнете зберігати свої команди до сценарію, пам’ятайте, що ви наближаєтесь до тарінгу Тюрінга . Наприклад, неможливо виявити збої в середині нормального трубопроводу . bashдодано set -o pipefailдля цього, але це не в POSIX.

Подібні корисні, але нестандартні функції надаються майже кожною утилітою, більш складною, ніж true.

Для класу задач, який ви окреслите, ви можете провести чорнову лінію до Awk, Perl і нині Python. Були створені різні засоби та розвивалися незалежно. Чи очікуєте ви, наприклад, що GNU Awk буде включений у розширений лібутілпосикс?

Я не кажу, що зараз у нас є один загально кращий підхід, на який я можу вас вказати. У мене м'яке місце для Python. Awk на диво потужний, хоча мене засмутили деякі особливості, характерні для GNU Awk. Але справа в тому, що обробка великої кількості рядків окремо (імовірно, з рядків файлів) не була ціллю дизайну оболонки POSIX.


Цікаво, чи не виникне труднощів із оболонкою, яка припускає, що будь-яка команда, виконана з налаштованого списку місць, буде розглядатися як вбудована у випадках, коли оболонка зрозуміла все про команду? Якщо скрипт виконує cat -@fnord fooоболонку, слід вирішити, що оскільки він не знає, що -@означає, що потрібно було б викликати фактичну команду, але, враховуючи лише cat <foo >barоболонку, не потрібно створювати інший процес.
supercat

1
@supercat складність.
sourcejedi

2

Існує також питання: в яку оболонку ви б вбудовували її?

Більшість систем Unix / Linux мають кілька різних оболонок, які розробляються незалежно (sh / bash / korn / ???). Якщо ви вбудуєте інструменти в оболонку, ви закінчилися різною реалізацією цих інструментів для кожної оболонки. Це може призвести до накладних витрат, і у вас можуть виникнути різні функції / помилки, наприклад, grep, залежно від того, яку оболонку ви використовували для виклику.


zsh досить популярний у деяких колах у наші дні. csh / tcsh історично мав велике переслідування, але я не думаю, що ви багато цього бачите сьогодні. А ще цілий набір маловідомих снарядів ...
CVn

Модульність. За допомогою вбудованих програм вам потрібно буде перекомпілювати або перевстановити оболонку щоразу, коли було внесено зміни до однієї з цих вбудованих файлів.
can-ned_food

1

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

Крім того, подумайте, якби такі функції, як sed або grep, були вбудовані в оболонку, було б так просто викликати командний рядок, коли вам це сподобається?

На закінчення, врахуйте, що частина функціональних можливостей, яких ви бажаєте бути в BASH, полягає в BASH . Наприклад, можливість узгодження RE в BASH реалізована за допомогою двійкового оператора = ~ (див. Граматику Shell на сторінці керівництва для більш детального посилання на обговорення конструкції [[]] для if ). Як дуже швидкий приклад, скажіть, що я шукаю файл з двома шістнадцятковими цифрами:

while read line; do
    if [[ $line =~ 0x[[:xdigit:]]{2} ]]; then
        # do something important with it
    fi
done < input_file.txt

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

# this does not take into account the saving of the substituted text
# it shows only how to do it
while read line; do
    ${line/pattern/substitution}
done < input_file.txt

Зрештою, чи вище "краще", ніж?

grep -E "[[:xdigit:]]{3}" input_file.txt
sed -e 's/pattern/substitution/' input_file.txt

Аргумент проти останнього питання можна знайти під unix.stackexchange.com/questions/169716/…
phk

1

Це, напевно, історична випадковість.

Коли UNIX був створений наприкінці 1960-х - початку 1970-х, комп'ютери не мали майже такої пам’яті, як сьогодні. Можливо, на той час можна було б реалізувати всю цю функціональність як оболонки, але через обмеження пам'яті їм довелося б обмежити кількість функціональних можливостей, які вони могли б реалізувати, або ризикувати втратою пам'яті та / або заміною кошиком. проблеми.

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

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

Це не означає, що ви не можете двічі реалізувати певну функціональність, і справді деякі оболонки реалізують певну функціональність, яка повинна бути зовнішньою програмою, як вбудована оболонка; наприклад, bash реалізує echoкоманду як вбудований, але є також a/usr/bin/echo

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