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

Раньше я делал сценарии Bash, и все они работали нормально без #!/bin/bash в начале.

Какой смысл вставлять? Было бы все иначе?

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

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


person node ninja    schedule 23.01.2012    source источник
comment
Вам не нужно и не нужно, если у вас нет выбора. Используйте '#! / Bin / sh', чтобы узнать о различиях между оболочкой (POSIX) и bash. Наступит день, прежде чем ваше резюме станет слишком длинным, когда вы окажетесь в системе с другой оболочкой, и вы все равно захотите, чтобы ваши скрипты работали.   -  person Jens    schedule 26.05.2012
comment
Это произносится как Hash-Bang или She-Bang.   -  person Beachhouse    schedule 09.01.2013
comment
Я думаю, стоит отметить, что это выполняется только в том случае, если вы запускаете свой скрипт как исполняемый файл. Таким образом, если вы установите флаг исполняемого файла, а затем наберете ./yourscript.extension, например, ./helloworld.py или ./helloworld.sh, он будет искать интерпретатор в этой верхней строке, которая будет #!/bin/python или !#/bin/bash, тогда как при выполнении сценария, такого как python helloworld.py, первая строка не будет наблюдаться, потому что это закомментировано. Так что это особая последовательность для оболочки / ядра.   -  person Jacqlyn    schedule 19.06.2015
comment
@JFA есть ли изменение в последовательности между bash и python при использовании! # Для python и #! для баш?   -  person AAI    schedule 30.08.2017
comment
@AjeyaAnand нет, это была опечатка, хороший улов   -  person Jacqlyn    schedule 30.08.2017
comment
Дополнительное чтение: medium.com/@codingmaths/   -  person carloswm85    schedule 17.07.2020


Ответы (10)


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

person paulsm4    schedule 23.01.2012
comment
Я обнаружил еще кое-что полезное, $ #. Как это называется? - person node ninja; 23.01.2012
comment
Shebang не является соглашением оболочки, он интерпретируется ядром при обработке execve(2) syscall; так что shebang - это соглашение ядра, а не оболочки. - person Basile Starynkevitch; 23.01.2012
comment
Кроме того, это помогает некоторым редакторам, таким как Vim, определять язык подсветки синтаксиса, если файл не имеет расширения. Без shebang Vim будет отображать сценарий bash так же, как обычный текстовый файл. - person Aaron Blenkush; 11.12.2013
comment
ps -u не может указать имя вашего файла сценария, если вы не добавите shebang. почему это? - person Rio Wing; 13.10.2016
comment
Это заставляет меня задуматься, нужно ли вам добавлять #!/bin/sh к таким вещам, как .profile и тому подобное, которое запускает onload - person Kellen Stuart; 18.10.2016
comment
Я видел много ответов на этот вопрос без реального объяснения, но последняя часть вашего ответа Исполняемый файл может быть двоичной программой, любым из миллиона типов скриптов и другими вещами. Следовательно, необходимость в #! / Bin / bash. действительно пришла - person senseiwu; 11.08.2018
comment
Итак ... hash-bang-slash-bin-slash-bash? - person Bernat; 31.01.2019
comment
.profile или .bashrc исходят, а не выполняются, поэтому не хотите начинать с символа #! - person Scott Stensland; 06.12.2019
comment
Обратите внимание, что официально (или исторически?) Shebang должен начинаться с #! /. Обратите внимание на пробел между восклицательным знаком и косой чертой. В результате первые четыре байта сценария начинаются с одного и того же магического значения: магического значения сценария оболочки. Это значение используется (использовалось), например, такой утилитой, как file, чтобы распознать, что это за файл. Конечно, в наши дни file и т. Д. Прекрасно распознают каждую оболочку, даже если большинство людей не учитывают пространство. - person Carlo Wood; 13.05.2020
comment
@Carlo Wood - ты прав насчет #! используется как магическое число - но ошибочно считают, что это 32-битное значение. Двухбайтовые магические числа не редкость: "#!" (23 21), "MZ" (4D 5A), "PK" (50 4B) и т. Д. И т. Д. - person paulsm4; 15.05.2020
comment
Я не сам придумал. - person Carlo Wood; 18.05.2020

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

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

Хороший трюк (или, возможно, не очень хороший), чтобы найти интерпретатор (например, python) в $PATH пользователя использовать программу env (всегда /usr/bin/env во всех Linux), например,

 #!/usr/bin/env python

Любой исполняемый файл ELF может быть интерпретатором. Вы даже можете использовать #!/bin/cat или #!/bin/true, если хотите! (но это часто было бы бесполезно)

person Basile Starynkevitch    schedule 23.01.2012
comment
См. этот вопрос для обсуждения взлома #!/usr/bin/env. - person Keith Thompson; 21.07.2013
comment
если я хочу передать аргумент python, как мне это сделать, на самом деле я хочу выполнить #!/usr/bin/env bash -x. Как я могу это сделать ? - person indianwebdevil; 15.05.2017
comment
это просто, я сам нашел это, просто добавьте параметр после этого #!/usr/bin/env bash -x - person indianwebdevil; 15.05.2017
comment
bash почти всегда на /bin/bash, так что ваш шебанг должен быть #!/bin/bash -x - person Basile Starynkevitch; 15.05.2017

Это называется shebang. На языке unix # называется резким (как в музыке) или хешем (как хэштеги в твиттере), и! называется челка. (На самом деле вы можете ссылаться на свою предыдущую команду оболочки с помощью !!, которая называется bang-bang). Итак, когда все вместе, вы получаете хаШ-БАНГ, или шебанг.

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

person austin1howard    schedule 23.01.2012
comment
Если я уже использую bash, запускает ли он другой экземпляр bash, если видит #! / Bin / bash? Что, если я уже использую bash и пропущу его? Есть ли разница? - person node ninja; 23.01.2012
comment
@javascriptninja в любом случае запускает новую оболочку bash. В случае с bash на самом деле нет никакой разницы, если вы уже используете bash. Shebang действительно имеет значение только в том случае, если (а) вам нужно запустить что-то, что не является просто оболочкой, например python или perl, или (б) вы не используете оболочку bash (т.е. вы используете zsh), но вам нужно запустить что-то, что требует запуска в bash. - person austin1howard; 23.01.2012
comment
Однако, на мой взгляд, это хорошая практика - включать shebang, чтобы кто-то, читающий код, знал, что происходит. - person austin1howard; 23.01.2012
comment
Неправильно: execve(2) системный вызов не использует переменную $SHELL. Это ядро ​​интерпретирует шебанг. - person Basile Starynkevitch; 23.01.2012
comment
@BasileStarynkevitch, это правильно, загрузчик elf в ядре интерпретирует shebang. Я заявлял, что $ SHELL будет использоваться, если не будет предоставлено shebang. - person austin1howard; 24.01.2012
comment
Я был очень удивлен, обнаружив, что пропуск #! работает даже для чего-то, запущенного из find -exec (т.е. не напрямую из оболочки). например с echo hello в /tmp/foo (исполняемый файл), strace и ltrace -f find [file] -exec /tmp/foo {} + показывает, что execvp(3) успешно: сначала он пытается execve(2), что, конечно, терпит неудачу с ENOEXEC (Exec format error), но затем возвращается к execveing /bin/sh /tmp/foo. Итак, ваше утверждение, что Unix попробует $ SHELL, ближе к правильному, чем я предполагал, благодаря помощи libc. Большинство программ не используют execve напрямую, но не- #! тогда сломается. - person Peter Cordes; 20.06.2016
comment
Я поддержал это, потому что это хорошо объясняет, почему я могу запускать сценарии bash без хэшбэга. Я побежал echo $SHELL, и результат был /bin/bash. Так что то, чего я раньше не знал. Спасибо. - person mikelovelyuk; 27.08.2017

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

person Balaswamy Vaddeman    schedule 23.01.2012

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

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

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

person Noufal Ibrahim    schedule 23.01.2012

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

Bash эволюционировал на протяжении многих лет, взяв код из ksh и sh.

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

#! часто называют «хэш-бэнг», «ша-бэнг» или «ша-бэнг».

person jaypal singh    schedule 23.01.2012

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

person Uday Sawant    schedule 23.01.2012

Стандарты Bash для «оболочки Bourne-Again» - это лишь один из множества доступных в Linux оболочек.

Оболочка - это интерпретатор командной строки, который принимает и запускает команды.

Bash часто является оболочкой по умолчанию в большинстве дистрибутивов Linux. Вот почему bash является синонимом оболочки.

Сценарии оболочки часто имеют почти одинаковый синтаксис, но иногда они различаются. Например, индекс массива начинается с 1 в Zsh, а не с 0 в bash. Сценарий, написанный для оболочки Zsh, не будет работать в bash, если в нем есть массивы.

Чтобы избежать неприятных сюрпризов, вы должны сообщить интерпретатору, что ваш сценарий оболочки написан для оболочки bash. Как ты это делаешь?

просто начните свой сценарий bash в #! / bin / bash

person Abdirahim Ali    schedule 17.04.2021

Также вы увидите некоторые другие параметры после #! / Bin / bash, например
#!/bin/bash -v -x
прочтите это, чтобы получить больше информации.
https://unix.stackexchange.com/questions/124272/what-do-the-arguments-v-and-x-mean-to-bash.

person star    schedule 04.04.2019

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

person Beardy    schedule 20.07.2013