Яка різниця між #! / Bin / sh і #! / Bin / bash?


280

якщо я напишу,

#!/bin/bash
echo "foo"

або

#!/bin/sh
echo "foo"

обидві врожаї однакові. Я бачив деякі сценарії, починаючи з #!/bin/shабо #!/bin/bash. Чи є різниця між ними?

Відповіді:


242

bashі shє двома різними оболонками. В основному bashце sh, з більшою кількістю функцій та кращим синтаксисом. Більшість команд працюють однаково, але вони різні.

Сказавши це, ви повинні зрозуміти, що /bin/shв більшості систем буде символічним посиланням і не посилатиметься sh. У Ubuntu /bin/shвикористовували посилання на bashтипову поведінку в дистрибутивах Linux, але тепер змінилися на посилання на іншу оболонку під назвою dash . Я б використовував bash, як це майже стандарт (або, принаймні, найпоширеніший з мого досвіду). Насправді проблеми виникають, коли буде використовуватися скрипт bash, #!/bin/shтому що виробник сценаріїв припускає, що посилання відбувається саме bashтоді, коли цього не повинно бути.

Для отримання додаткової інформації http://man.cx/sh , http://man.cx/bash .


24
Ваш перший абзац є досить оманливим. "sh" - це зовсім не оболонка, а симпосилання на поточно налаштовану системну оболонку , яка в системах Linux зазвичай є bash або dash (останні версії Ubuntu, що використовують останні).
thomasrutter

18
/bin/shРаніше в 1977 році використовувалася оболонка під назвою бурнова оболонка . bash - це сумісна оболонка / bin / sh, яка може бути використана як заміна оболонки бурна, яка відповідає позиції. en.wikipedia.org/wiki/Bourne_shell
Алекс

5
bash - це фактично стандарт (дуже широко використовується), але він не є "стандартним"; sh на Ubuntu використовує тире , яке є сумісною з Posix оболонкою, тому це дійсно стандарт. Моя порада - використовувати тире якомога частіше для сценаріїв, особливо для сценаріїв на стороні сервера. Хоча bash більш виразний, тире бігає досить швидше і є більш захищеним.
Rick-777

@ Rick-777 Тож я повинен явно поставити #! / Bin / dash у верхній частині моїх сценаріїв? Я також написав сценарії, де я лише пишу команди та виконую з ./scriptName, і це добре працювало. Чи потрібен #! / Bin / yourShellHere?
користувач137717

@ Rick-777 У тих випадках, коли я виключаю будь-який #! / Bin / shellName, я назвав файли fileName.sh. Чи буде це неявно посилатися на бажану системну оболонку без оголошення #! / Bin / sh?
користувач137717

82

У Linux та інших системах, схожих на Unix, у вас є вибір декількох оболонок.

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

bash - це найпоширеніша оболонка, яка використовується як оболонка за замовчуванням для користувачів систем Linux. Це духовний нащадок інших оболонок, які використовувались протягом усієї історії Unix. Його назва, bash - це абревіатура Bourne-Again Shell, що вшановує оболонку Борна, яку вона була розроблена для заміни, хоча вона також містить функції C Shell і Korn Shell.

Цього дня вона запущена з /bin/bash- будь-яка система з bash матиме її тут.

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

Проблема полягає в тому, що різні оболонки мають між собою крихітні невеликі невідповідності, і коли справа доходить до запуску сценаріїв, це може бути справжньою проблемою. bash має досить багато можливостей сценаріїв, унікальних лише для bash, а не для інших оболонок. Це добре, якщо ви завжди будете використовувати bash для запуску цих сценаріїв. Інші оболонки можуть спробувати або імітувати bash, або дотримуватися стандарту POSIX, який bash підтримує досить добре (хоча додає власні розширення).

Можна в верхній частині сценарію оболонки вказати, з якою оболонкою слід запустити за допомогою shebang. У #!/bin/bashпершому рядку може бути вказаний скрипт, тобто сценарій завжди повинен працювати з bash, а не з іншою оболонкою.

/ bin / sh - виконуваний файл, що представляє оболонку системи . Насправді він зазвичай реалізується як символічне посилання, що вказує на виконуваний файл, залежно від того, яка оболонка є системною оболонкою. Системна оболонка - це різновид оболонки за замовчуванням, яку повинні використовувати системні скрипти. У дистрибутивах Linux протягом тривалого часу зазвичай це було символічним посиланням на bash , настільки, що це стало дещо конвенцією завжди посилати / bin / sh на bash або bash-сумісну оболонку. Однак в останні пару років Debian (і Ubuntu) вирішили переключити системну оболонку з bash на тире- аналогічна оболонка - порушення з давньою традицією в Linux (ну, GNU) використання bash for / bin / sh. Dash розглядається як легша і набагато швидша оболонка, яка може бути корисною для швидкості завантаження (та інших речей, для яких потрібна велика кількість скриптів оболонки, наприклад, сценарії встановлення пакунків).

Dash досить добре сумісний з bash, будучи на основі того ж стандарту POSIX. Однак він не реалізує специфічні для bash розширення. Існують сценарії, які використовують #!/bin/sh(оболонку системи) як їх шебанг, але для цього потрібні розширення, характерні для bash. В даний час це вважається помилкою, яку повинні виправити Debian і Ubuntu, які вимагають / bin / sh, щоб мати можливість працювати при вказівці на тире.

Навіть незважаючи на те, що системна оболонка Ubuntu вказує на тире, ваша оболонка для входу як користувач продовжує базуватися. Тобто, коли ви ввійдете в емулятор терміналу в будь-якій точці Linux, ваша оболонка входу буде баш. Швидкість роботи не стільки проблема, коли оболонка використовується інтерактивно, і користувачі знайомі з bash (і можуть мати налаштування, характерні для bash, у своєму домашньому каталозі).

Що слід використовувати при написанні сценаріїв

Якщо ваш сценарій вимагає функцій, які підтримуються лише bash, використовуйте #!/bin/bash.

Але якщо це взагалі можливо, було б добре переконатися, що ваш скрипт сумісний з POSIX, і використовувати #!/bin/sh, що завжди, досить надійно, повинно вказувати на бажану системну оболонку, сумісну з POSIX, у будь-якій установці.


18

На додаток до попередніх відповідей, навіть якщо /bin/shце символічне посилання на /bin/bash, #!/bin/shне зовсім рівнозначно #!/bin/bash.

З сторінки bash (1) man :

"Якщо bash викликається ім'ям sh, він намагається максимально наблизити поведінку до запуску історичних версій sh, дотримуючись стандарт POSIX."

Наприклад синтаксис bash:

 exec  > >(tee logfile.txt)

дає помилку в оболонці, починаючи з #!/bin/sh, навіть якщо на місці є символічне посилання sh-> bash.


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