Зачем вам нужно ставить #! / Bin / bash в начале файла скрипта?

487

Я делал скрипты на Bash раньше, и все они работали нормально #!/bin/bashв начале.

Какой смысл вкладывать это в? Будет ли что-то другое?

Кроме того, как вы произносите #? Я знаю, что !произносится как «взрыв».

Как #!произносится?

узел ниндзя
источник
8
Вам не нужно и не нужно, если у вас нет выбора. Используйте «#! / Bin / sh», чтобы узнать разницу между оболочкой (POSIX) и bash. Придет день, прежде чем ваше резюме станет слишком длинным, когда вы окажетесь в системе с другой оболочкой и захотите, чтобы ваши скрипты работали.
Дженс
50
Это произносится как "Hash-Bang" или "She-Bang".
Домик на пляже
22
Я думаю, стоит отметить, что это выполняется только в том случае, если вы запускаете свой скрипт как исполняемый файл. Поэтому, если вы установите флаг исполняемого файла и затем наберете ./yourscript.extension, например, ./helloworld.pyили ./helloworld.sh, он будет искать интерпретатор в той верхней строке, который будет равен #!/bin/pythonили !#/bin/bash, тогда как при выполнении сценария, подобного python helloworld.py, первая строка не будет наблюдаться, потому что она закомментирована вне. Так что это особая последовательность для оболочки / ядра.
JFA
@JFA: есть ли изменение в последовательности между bash и python при использовании! # Для python и #! для Баш?
AAI
1
@AjeyaAnand нет, это был опечатка, хороший улов
JFA

Ответы:

426

Это соглашение, поэтому оболочка * 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.

paulsm4
источник
1
Я узнал о чем-то еще полезном, $ #. Как это называется?
узел ниндзя
91
Шебанг не является соглашением оболочки , он интерпретируется ядром при обработке execve(2)системного вызова; так что шебанг - это соглашение ядра , а не оболочка.
Василий Старынкевич
10
Кроме того, это помогает некоторым редакторам, таким как Vim, определить язык для подсветки синтаксиса, если файл не имеет расширения. Без шебанга Vim будет отображать скрипт bash, такой же, как простой текстовый файл.
Аарон Бленкуш
1
Это заставляет меня задуматься, нужно ли вам добавлять #!/bin/shтакие вещи, как .profileи вещи, которые работают под нагрузкой
Колоб Каньон
5
Итак ... хэш-бэнг-слэш-бин-слэш-бэш ?
Бернат
135

Чтобы быть более точным, shebang #! , когда это первые два байта исполняемого файла ( x режима ), интерпретируется системным вызовом execve (2) (который выполняет программы). Но в спецификации POSIXexecve не упоминается шебанг.

За ним должен следовать путь к файлу исполняемого файла интерпретатора (что, кстати, может даже быть относительным, но чаще всего абсолютным).

Хорошая уловка (или, возможно, не очень хорошая ), чтобы найти переводчика (например 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
Старынкевич
50

Это называется шебанг . В Unix-говорят, # называется острым (как в музыке) или хэш (как хэштеги в твиттере), и! называется взрыв. (Вы можете сослаться на свою предыдущую команду оболочки с помощью команды !!, называемой bang-bang). Таким образом, когда вы соберетесь вместе, вы получите ха-бэнг или шебанг.

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

austin1howard
источник
2
Если я уже в bash, запускается ли другой экземпляр bash, если он видит #! / Bin / bash? Что делать, если я уже в Bash, и я оставлю это? Есть ли разница?
узел ниндзя
2
@javascriptninja в любом случае запускает новую оболочку bash. В случае bash на самом деле нет никакой разницы, если вы уже используете bash. Шебанг действительно имеет значение, только если (а) вам нужно запустить что-то, что не является просто оболочкой, например, python или perl, или (б) вы не используете оболочку bash (т.е. вы используете zsh), но вам нужно запустить то, что требует запуска в bash.
austin1howard
Тем не менее, по моему мнению, хорошей практикой является включение «шебанга», чтобы кто-нибудь, читающий код, знал, что происходит.
austin1howard
2
Неправильно: execve(2)системный вызов не использует $SHELLпеременную. Это ядро ​​интерпретирует Шебанг.
Василий Старынкевич
1
@BasileStarynkevitch, что верно, загрузчик эльфов в ядре интерпретирует шебанг. Я заявлял, что $ SHELL будет использоваться, если не будет предоставлен шебанг.
austin1howard
19

Притон директива загрузчика использовать программу , которая указана после того , #!как интерпретатор для файла в вопросе , когда вы пытаетесь выполнить. Таким образом, если вы попытаетесь запустить файл с именем , foo.shкоторый имеет #!/bin/bashв верхней части, фактическую команду , которая работает на /bin/bash foo.sh. Это гибкий способ использования разных переводчиков для разных программ. Это то, что реализовано на системном уровне, а API уровня пользователя - это соглашение Шебанга.

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

Ваше мнение о том, что он «работает» даже без шебанга, заключается только в том, что рассматриваемая программа представляет собой сценарий оболочки, написанный для той же оболочки, что и та, которую вы используете. Например, вы могли бы очень хорошо написать файл javascript и затем поместить #! /usr/bin/js(или что-то подобное), чтобы иметь javascript «Shell script».

Нуфал Ибрагим
источник
18

Операционная система использует оболочку по умолчанию для запуска вашего сценария оболочки. упомянув путь к оболочке в начале скрипта, вы просите ОС использовать именно эту оболочку. Это также полезно для мобильности .

Баласвами Ваддеман
источник
15

Каждый дистрибутив имеет оболочку по умолчанию. Bash используется по умолчанию в большинстве систем. Если вы работаете в системе с другой оболочкой по умолчанию, сценарии могут работать не так, как задумано, если они написаны специально для Bash.

Bash развивался годами, принимая код от kshи sh.

Добавление #!/bin/bashв качестве первой строки вашего сценария указывает операционной системе вызывать указанное shellдля выполнения команд, которые следуют в сценарии.

#! часто упоминается как "хэш-бэнг", "она-бэнг" или "ша-бэнг".

Джайпал Сингх
источник
9

Это называется шебанг . Он состоит из знака числа и символа восклицательного знака (#!), За которым следует полный путь к интерпретатору, например / bin / bash. Все сценарии в UNIX и Linux выполняются с использованием интерпретатора, указанного в первой строке.

Удай Савант
источник
0

Это может быть полезно для тех, кто использует другую систему, для которой эта библиотека не доступна. Если это не объявлено, и в вашем скрипте есть некоторые функции, которые не поддерживаются этой системой, вы должны объявить # / bin / bash. Я столкнулся с этой проблемой раньше, чем на работе, и теперь я просто включаю ее в качестве практики.

бородачей
источник