Чи є якась причина, щоб shebang вказував на / bin / sh, а не на / bin / bash?


53

У більшості сценаріїв оболонки я бачив (крім тих , що я не писав сам), я помітив , що притон встановлений #!/bin/sh. Це не дуже мене дивує на старих сценаріях, але воно є і на досить нових сценаріях.

Чи є підстави для переваги /bin/shбільш /bin/bash, так як bashце в значній мірі повсюдно, і часто по замовчуванням, на багатьох машинах Linux і BSD висхідних більше десяти років?


23
Це хороша частка, /bin/shякщо ви не використовуєте конкретні bashфункції. Одного разу вам довелося б використовувати один зі своїх скриптів у системі, на якій він не встановлений (віддалений сервер, вбудований комп'ютер ...)
Матьє

1
в цілому вам слід уникати запитань, які піддаються відповідям на основі думки (це єдиний можливий спосіб, на який я вважаю, що на це питання можна відповісти - але це лише моя думка ) .
mikeserv

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

3
@JulesMazur ...the answers so far are fairly subjective..."Суб'єктивне" твердження по суті засноване на думці. /bin/bashслід використовувати лише тоді, коли явно потрібен bash. За 40 років як розробник, задовго до цього bashя майже ніколи не потребував цього, за винятком тестування. (Я також прагну уникати розширень оболонок, але більшість моїх сценаріїв призначені для розповсюдження.) Багато сценаріїв в мережі також повинні бути призначені для широкого використання.
користувач2338816

2
@ user2338816 мені погано, я мав на увазі об'єктивний . Дякуємо за ваші бали!
Жуль

Відповіді:


83
  1. Існують системи, що не доставляють bash за замовчуванням (наприклад, FreeBSD).
  2. Навіть якщо встановлено bash, він може не знаходитися в /bin.
  3. Для більшості простих сценаріїв не потрібен bash.
  4. Використання оболонки POSIX є більш портативним, і сценарії працюватимуть у різних системах.

17
Ще одна причина: часто / bin / sh швидше, ніж bash, або принаймні швидше завантажується (через те, що він менший).
дероберт

5
@derobert, /bin/shшвидше, якщо його немає bash, все ж є кілька систем, таких як OS / X або RHEL, де /bin/shє bash.
Стефан Шазелас

1
Ні. Деякі ОС пов'язують це, тому що bash сумісний назад.
Sobrique

7
Дуже кілька сценаріїв припускають, що /bin/shце так /bin/bash. Перехід Ubuntu з bash на тире розбив їх усіх.
отаманроман

19
@atamanroman: Сценарії в першу чергу були невірними, вони повинні були використовувати, #!/bin/bashякби хотіли Баша (нічого поганого в цьому!). Зміна в основному була здійснена вище за течією в Debian. Це покращило користувальницький досвід, мало помітний вплив на час запуску системи. Це також позитивно вплинуло на безпеку, див. "Shellshock".
Дітріх Епп

28

Більшість системних сценаріїв (пов'язані з Debian: Ubuntu, Mint тощо) для Linux написані для запуску в більш швидкому тирі, що є типовим / bin / sh у цих системах. Причина двояка:

  • Швидкість роботи системи. Менший код тире завантажується швидше, а також працює швидше. З деякими (невеликими?) Додатковими зусиллями (витратами) на програмістів скриптів оболонок.

  • Безпека. Наявність різноманітності раковин сприяє стійкості до помилок. Системи Debian здебільшого не були вразливими до обстрілу, оскільки оболонка за замовчуванням не мала такої вразливості.

Bash - це справді оболонка для користувачів за замовчуванням , оскільки вона є більш потужною та має набагато більше елементів, щоб полегшити кодування. Це також за замовчуванням shу Mac OS (пов'язаний з / bin / sh). Однак виклик bashз назвою посилання shзмушує його починатись як оболонка, сумісна з позицією.


2
Більш обмежений набір доступних інструментів простішої оболонки ускладнює написання коду (будь ласка, уникайте будь-якої фанатичної війни з цього приводу). Ось чому деяким користувачам подобається zsh, який має навіть більше інструментів, ніж bash. Мені більше подобається Баш, оскільки це баланс між обома крайнощами.

4
@RobertL, багато засобів, доданих у ksh та прийнятих bash, існують, оскільки вони суттєво полегшують процес написання надійних та правильних сценаріїв. Без різних доповнень, що дозволяють безпечно виконувати непряме присвоєння та оцінку, наприклад, можна знайти себе, використовуючи evalсупровідну безпеку; аналогічно, без вбудованої підтримки регулярних виразів, вам потрібно буде використовувати зовнішні команди (при важкому покаранні) для відповідності навіть в одному рядку тощо.
Чарльз Даффі

1
@RuiFRibeiro, в Debian нічого статично не пов'язане. Dash є більш обмеженим, але він обмежений, головним чином, в інтерактивних функціях (без завершення і подібних), так що це швидше для сценаріїв.
Ян Худек

21

Інші зазначають, що суперечки питання про те, що оболонка Bourne Again є типовою та всюдисущою, прямо невірно.

На додаток до цього, дійсно є вагомі причини використовувати щось інше, ніж оболонку Bourne Again для інтерпретації скриптів оболонок. Ці причини мотивовано великий проект в Ubuntu і Debian, в протягом ряду років, щоб видалити bashisms і зробити так як багато хто з сценаріїв оболонки керують ініціалізації системи (який був багато сценаріїв оболонки з системою 5 rc) і пакет установки / видалення використовувати Оболонка Debian Almquist замість оболонки Bourne Again.

Простіше кажучи: оболонка Bourne Again, обшита повною мірою інтерактивними функціями, не є найшвидшим інтерпретатором оболонки для сценарію оболонки, сумісної з POSIX. Тож якщо ви можете зробити свої сценарії оболонки, сумісні з POSIX, інтерпретуючи їх за допомогою більш легкої програми, як оболонка Debian Almquist, система буде працювати краще. (Зрештою, Debian довелося внести невеликі корективи в оболонку Almquist, щоб додати підтримку для кількох конструкцій оболонок, які не є POSIX, які були просто занадто глибоко вбудовані і занадто корисні, щоб позбутися.)

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

Отже, тут слід розглянути два різних класи оболонки:

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

Зауважте, що говорити про це як про «перевагу /bin/sh» є надто спрощеним. Debian фактично мав принаймні дві цілі:

  1. На очах у адміністраторів, що використовують оболонку Debian Almquist, Z Shell (в режимі POSIX), оболонку Bourne Again (в режимі POSIX), оболонку MirBSD Korn та інші, тому /bin/shщо було…

    1. … Зробити сценарії максимально портативними, щоб переключення того, що /bin/shвідображено, не порушувало речі; або

    2. … Створення не портативних сценаріїв явно орієнтується на правильну програму інтерпретатора , а не просто очікувати на цю /bin/shкарту.

  2. Там робилася оболонка Debian Almquist за замовчуванням для заміни оболонки /bin/shBourne, щоб ті сценарії, які відповідають POSIX (або, правильніше, відповідно до Посібника Debian Policy), бігали швидше.

І звичайно, як тільки хтось в цьому потрапить, можна зробити це набагато далі; таких як розгляд компромісних ефективності подібних /bin/trueі /usr/bin/clearбути сценаріїв оболонки або скомпільовані програми. Але це виходить за рамки цієї відповіді, на щастя. ☺

Ніщо з цього не є дуже новим, навіть навіть для Unix, звичайно. Ще до початку межі століття я написав і опублікував інтерпретатор командного рядка, який входив як в "інтерактивний", так і в "неінтерактивний" смаки, пояснюючи цей самий поділ в його документі і зазначаючи різницю між змінними COMSPECі OS2_SHELLсередовищем. Аналогічно, обговорення видалення башизмів у Debian System V rcта сценаріїв встановлення / видалення пакунків починається з 1990-х.

Подальше читання


2
"Врешті-решт, Debian довелося внести невеликі корективи в оболонку Almquist, щоб додати підтримку для декількох конструкцій оболонок, які не є POSIX, які були просто занадто глибоко вбудовані і занадто корисні, щоб позбутися." - Яке з ваших численних посилань містить інформацію про це? Це звучить дуже цікаво. :)
Wildcard

3
ІМХО, продуктивність - лише мотивація для того, щоб змусити людей погодитися зі змінами. Початкова велика причина зміни полягала в тому, що баш продовжував порушувати зворотну сумісність. Мені особисто доводилося виправляти проблеми bash хоча б 3 рази в моїй кар’єрі, оскільки сценарій працюватиме в одній версії bash, але в іншому не вдався (зазвичай це відбувається після оновлення ОС). Dash - це не просто трохи швидший перекладач. Це також набагато стійкіше в плані поведінки.
slebetman

Мені буде цікаво, чи підходять коментарі на Schily Bourne Shellсторінці людини, див. Schilytools.sourceforge.net/bosh.html , щоб люди могли зрозуміти, як написати портативний сценарій (це залежить лише Bourne Shell featuresвід 1989 року). Те, що я робив, згадувало про кожне вдосконалення, яке не було в старих Борнських оболонках. BTW: Мені також цікаво ознайомитись із списком башизмів.
шилі

8

Чи є якась причина, щоб shebang вказував на / bin / sh, а не на / bin / bash?

Так. @ Відмінна відповідь Марко це добре окреслює.

Що я повинен використовувати в моєму шебангу?

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

У моїй системі (Centos 6.6), shпосилається на bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Це означає, що я завжди використовую #!/bin/bashв своєму шебангу, якщо я не підтвердив, що в моєму сценарії немає башимів.

Встановивши shebang, #!/bin/shви обіцяєте, що сценарій буде працювати з усіма реалізаціями sh.

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

Ось приклад сценарію, який буде поводитись неправильно, залежно від того, shяку систему використовує система:

#!/bin/sh
n=1
a=$((++n))
echo $n

При використанні bashсценарію буде надруковано:

2

При використанні dashсценарію буде надруковано:

1

Якщо я хочу використовувати #!/bin/shте, що мені потрібно зробити?

  • Перевірте сценарій за допомогою checkbashisms- Зауважте, що це не знайде всіх башімів. Це не знайшло башизму в моєму сценарії вище
  • Тестуйте сценарій за допомогою іншої shреалізації. Я, як правило dash, тестую, однак я очікую, що деякі башими чи дашіми все ще можуть проскочити.

На сторінці DashAsBinSh на вікі Ubuntu є багато цікавої інформації.


6
"Під час написання власних сценаріїв слід вказати на shebang на найзагальніше, на що ви протестували .... Встановивши shebang на #! / Bin / sh, ви обіцяєте, що сценарій буде працювати з усіма реалізаціями sh . " Відмінний момент. +1, і ти змусив мене переосмислити, як я буду писати свої шебанги на майбутнє. Дякую! :)
Wildcard

2
Ну, не всі реалізації /bin/sh; лише сумісні з POSIX.
Blacklight Shining

4

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

/bin/shє єдиним інтерпретатором скриптів, який доступний для всього, що називає себе Unix. Але на надзвичайно багато застарілих систем /bin/shта пов'язаних з ними утиліт навіть не відповідають специфікації POSIX.1-1996 "оболонки та утиліти", не кажучи вже про щось більш сучасне. Інструменти, сумісні зі стандартами, - це додаткові додатки, встановлені в тому /usr/xpg4чи іншому такому неочевидному місці. 1 Сценарій на мову оболонки переносного підмножини є ще більш стомлюючим та схильним до помилок, ніж написання мови оболонки POSIX. ( configureКолись ви не повірите мені, перечитайте сценарій, створений автоматичним конфором, якщо ви мені не вірите. Просто налаштування має бути достатньо, щоб переконати вас.)

Але якщо ви можете припустити, що інший інтерпретатор скриптів встановлений (наприклад, Bash), то ви можете припустити, що для кращої мови сценаріїв встановлений перекладач. Perl, наприклад, є більш ймовірно, будуть доступні , ніж Bash є.

Тому ніколи не слід писати #! /bin/bashсценарій, адже якщо це варіант, краща мова - це також варіант.

1 Наприклад, Solaris 10 та старші поставляли оригінал оболонки Борна як /bin/sh. Мені інформують, що Solaris 11 оновив його до ksh93.


3
Якою мовою ви будете писати сценарій для завантаження системи? Або всередині маршрутизатора SOHO (системи з обмеженим нахилом)? Або в Android? Оболонка буде доступна у всіх цих випадках. Перл ні.

1
Є деякі неточності щодо пов’язаних з Solaris частин вашої відповіді. У програмі Solaris 10 і пізніших версій - /bin/shце не POSIX.1-1996, а фактично оригінальна оболонка Bourne-синтаксису перед POSIX. Це робить #!/bin/shдуже бідним шебанг для сценаріїв для роботи з цими випусками. Використовуються портативні сценарії на Solaris, #!/usr/xpg4/bin/shякі не будуть дуже портативними в інших ОС. Остання версія Solaris Oracle Solaris 11 вперше випущена в 2011 році /bin/sh- це сучасний, ksh93який відповідає останнім специфікаціям POSIX та має багато сучасних розширень.
jlliagre

1
@BinaryZebra: "Оболонка" буде доступна, так. Але bash - це не обов'язково така оболонка (зокрема, більшість маршрутизаторів SOHO використовують, ashяка надається зайнятим ящиком), і я схильний вважати, що zwol має рацію, що Perl є більш поширеним, ніж bash.
Бен Войгт

1
@BenVoigt Я коментую це речення "Єдиний приклад для написання сценарію оболонки". Є ще деякі випадки, для яких потрібна оболонка для деяких завдань (не для всіх). Це були деякі випадки зверху моєї голови. OTOH У системах з достатньою кількістю пам'яті (майже всі сьогоднішні стандарти) і достатньою потужністю встановлення Perl (або Python, або ....) досить швидко і просто. Однак я не виступаю за будь-яку конкретну оболонку. Де ти це читаєш у моєму коментарі?

2
Цілком не погоджуйтеся з вашою твердим і нефактичним твердженням, що "якщо bashце доступно, тоді це краща мова, тому ніколи не слід писати жодного bashкоду". Крім того, як вказує @sixtyfootersdude, ви завжди повинні використовувати, #!/bin/bashякщо ви не перевірили, що ваш сценарій працює з будь-якою оболонкою POSIX.
Wildcard

0

Ви насправді використовуєте будь-яке

#! /bin/env sh

або

#! /bin/env bash

таким чином ви викликаєте будь-яку оболонку шляхом їх встановлення в цій системі.

Щоб бути супербезпечним ( наприклад, у випадках перезавантаження одного користувача), використовуйте shінше bash.


6
З цієї відповіді : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Це, мабуть, стосується shі bash.
Жуль

12
Ні, #!/bin/envу портативному сценарії нічого не слід використовувати . Цілком розумно припустити, що /bin/shіснує і є робочою оболонкою, сумісною з POSIX. З іншого боку, жодна з моїх систем не має /bin/env.
Blacklight Shining

Також хороший момент.
Жуль

1
@Blacklight Shining, безумовно, неправильно вважати оболонку, сумісну з POSIX /bin/sh. POSIX цього не вимагає, і, скоріше, визначає інші правила для отримання середовища, сумісного з POSIX, на платформі, сертифікованої POSIX.
schily

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