Чому потрібно ставити #! / Bin / bash на початку файлу сценарію?


485

Я раніше робив сценарії Баша, і всі вони чудово проходили без #!/bin/bashпочатку.

Який сенс вводити його? Чи все було б інакше?

Також, як ви вимовляєте #? Я знаю, що !вимовляється як "удар".

Як #!вимовляється?


8
Вам не потрібно і не слід, якщо у вас немає вибору. Використовуйте "#! / Bin / sh", поки ви можете і дізнаєтесь про різницю між (POSIX) оболонкою та bash. Наступить день, коли ваше резюме зросте занадто довше, коли ви опинитеся в системі з іншою оболонкою, і ви все ще хочете, щоб ваші сценарії працювали.
Єнс

50
Це вимовляється "Hash-Bang" або "She-Bang".
Beachhouse

22
Я думаю, що варто відзначити, що це виконується лише в тому випадку, якщо ви запускаєте свій сценарій як виконуваний файл. Отже, якщо ви встановите прапор, що виконується, а потім введіть ./yourscript.extension, наприклад, ./helloworld.pyабо ./helloworld.sh, він буде шукати інтерпретатора у тому верхньому рядку, який би був #!/bin/pythonабо !#/bin/bash, тоді як при виконанні сценарію типу python helloworld.py, перший рядок не буде спостерігатися, оскільки він коментується з. Отже, це спеціальна послідовність для оболонки / ядра.
JFA

@JFA - це зміна послідовності між bash та python, коли використовується! # Для python та #! за баш?
AAI

1
@AjeyaAnand ні, це була помилка, хороший улов
JFA

Відповіді:


425

Це умовна умова, тому оболонка * nix знає, яким інтерпретатором працювати.

Наприклад, старіші аромати ATT дефолтували до sh (оболонка Bourne), тоді як старіші версії BSD дефолт до csh (оболонка C).

Навіть сьогодні (де більшість систем працює bash, "Bourne Again Shell" ) сценарії можуть бути в bash, python, perl, ruby, PHP тощо тощо. Наприклад, ви можете побачити #!/bin/perlабо #!/bin/perl5.

PS: знак оклику ( !) ласкаво називається "удар" . Символ коментаря до оболонки ( #) іноді називають "хеш" .

PPS: Пам’ятайте - під * nix асоціація суфікса з типом файлу - це лише умова , а не «правило» . Виконавчим файлом може бути двійкова програма, будь-який з мільйона типів скриптів та інші речі. Звідси потреба в #!/bin/bash.


1
Я дізнався про щось інше корисне, $ #. Як це називається?
вузол ніндзя

91
Шебанг не є умовою оболонки , вона інтерпретується ядром при обробці execve(2)системного виклику; тож шебанг - це умова ядра , а не оболонка.
Базиль Старинкевич

10
Крім того, це допомагає деяким редакторам, як Vim, визначати мову виділення синтаксису, якщо файл не має розширення. Без шебангу Vim покаже скрипт bash, такий же, як і звичайний текстовий файл.
Аарон Бленкуш

1
Це змушує мене задатися питанням, чи потрібно додати #!/bin/shдо речей , як .profileі матеріал , який працює OnLoad
Колоб Каньйон

5
Отож ... хеш-баг-слэш-бін-слэш-баш ?
Бернат

134

Якщо точніше, шебанг #! , коли це перші два байти виконуваного файлу ( x режиму ), інтерпретується системним викликом execve (2) (який виконує програми). Але специфікація POSIX дляexecve не згадує про шебанг.

Слід дотримуватися шлях файлу виконуваного інтерпретатора (який BTW навіть може бути відносним, але найчастіше є абсолютним).

Приємний трюк (або, можливо, не такий приємний ), щоб знайти інтерпретатора (наприклад python) у користувача, $PATHце використовувати envпрограму (завжди /usr/bin/envна всіх Linux), наприклад,

 #!/usr/bin/env python

Будь-який виконуваний файл ELF може бути перекладачем. Ви навіть можете користуватися #!/bin/catабо #!/bin/trueхочете! (але це було б часто марно)


8
Дивіться це питання для обговорення #!/usr/bin/envзлому.
Кіт Томпсон

якщо я хочу передати аргумент python, як це зробити, насправді я хочу виконати #!/usr/bin/env bash -x. Як мені це зробити?
indianwebdevil

його просто я знайшов, просто додайте парам після цього#!/usr/bin/env bash -x
indianwebdevil

bashмайже завжди є, /bin/bashтому має бути ваш шебанг#!/bin/bash -x
Базиле Старинкевич

49

Це називається шебанг . У unix-говорінні # називається різким (як у музиці) або хешем (як хештеги на Twitter), і! називається чубком. (Насправді ви можете посилатися на свою попередню команду оболонки за допомогою !!, що називається bang-bang). Тож, склавши разом, ви отримуєте haSH-BANG, або shebang.

Частина після #! повідомляє Unix, яку програму використовувати для його запуску. Якщо він не вказаний, він буде намагатися з bash (або sh, або zsh, або будь-якою вашою змінною $ SHELL), але якщо він є, він буде використовувати цю програму. Крім того, # - це коментар на більшості мов, тому рядок ігнорується при наступному виконанні.


2
Якщо я вже в bash, чи запускає інший екземпляр bash, якщо він бачить #! / Bin / bash? Що робити, якщо я вже перебуваю в баші і не залишаю його? Чи є різниця?
вузол ніндзя

2
@javascriptninja так чи інакше запускає нову оболонку bash. Що стосується bash, насправді різниці немає, доки ви вже використовуєте bash. Shebang має значення лише в тому випадку, якщо: (а) вам потрібно запустити щось, що не є просто оболонкою, наприклад, python або perl, або (b) ви не використовуєте оболонку bash (тобто ви використовуєте zsh), але вам потрібно запустити щось, що вимагає запуску в баш.
austin1howard

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

2
Неправильно: execve(2)syscall не використовує $SHELLзмінну. Саме ядро ​​тлумачить шебанг.
Базиль Старинкевич

1
@BasileStarynkevitch це правильно, ельфі-завантажувач в ядрі інтерпретує shebang. Я заявив, що $ SHELL буде використано, якщо не буде надано шебанг.
austin1howard

19

притон директива завантажувача використовувати програму , яка вказана після того , #!як інтерпретатор для файла в питанні , коли ви намагаєтеся виконати. Отже, якщо ви спробуєте запустити файл, foo.shякий називається #!/bin/bashу верхній частині, фактична команда, яка виконується, є /bin/bash foo.sh. Це гнучкий спосіб використання різних перекладачів для різних програм. Це щось реалізоване на системному рівні, а API рівня користувача - це конвенція shebang.

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

Ваша думка про те, що вона "працює" навіть без шебанга, лише тому, що програма, про яку йдеться, - це сценарій оболонки, написаний для тієї ж оболонки, що і той, який ви використовуєте. Наприклад, ви можете дуже добре написати файл javascript, а потім поставити #! /usr/bin/js(або щось подібне), щоб він мав "скрипт оболонки".


18

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


15

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

Баш еволюціонував протягом багатьох років, беручи код з kshі sh.

Додаючи #!/bin/bashв якості першого рядка свого сценарію, вказує ОС викликати вказані shellдля виконання команд, що слідують у сценарії.

#! часто називають "хеш-баг", "вона-баг" або "ша-баг".


9

Це називається шебанг . Він складається із знака числа та символу оклику (#!), Після якого йде повний шлях до перекладача, такого як / bin / bash. Усі сценарії під UNIX та Linux виконуються за допомогою інтерпретатора, зазначеного в першому рядку.



0

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

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