В сценарии необходимо включать a #!
на первой строке, сопровождаемой путем к программе, которая выполнит сценарий (например: sh, жемчуг).
Насколько я знаю, #
символ обозначает запуск комментария, и та строка, как предполагается, проигнорирована программой, выполняющей сценарий. Это казалось бы, что эта первая строка в какой-то момент читается чем-то для сценария, который будет выполняться надлежащей программой.
Мог кто-то проливать больше света на работы #!
?
Мне действительно любопытно на предмет этого, таким образом, чем более всесторонний ответ, тем лучше.
Рекомендуемая литература:
За это отвечает загрузчик программ ядра unix. Когда вызывается exec ()
, он просит ядро загрузить программу из файла по своему аргументу. Затем он проверит первые 16 бит файла, чтобы узнать, какой у него исполняемый формат. Если он обнаружит, что это #!
он будет использовать оставшуюся часть первой строки файла, чтобы определить, какую программу он должен запустить, и предоставит имя файла, который он пытался запустить (сценарий), в качестве последнего аргумента программы интерпретатора.
Затем интерпретатор работает в обычном режиме и обрабатывает #!
в качестве комментария.
Краткая история: Строка shebang (#!
) читаетсяоболочкой (например, загрузчика программ операционной системы. Хотя формально это выглядит как комментарий, тот факт, что это самые первые два байта файла, маркирует весь файл как текстовый файл и как сценарий. Сценарий будет передан исполняемому файлу, упомянутому в первой строке после shebang. Вуаля! sh
, bash
и т.д.)
Немного более длинная история: Представьте, что у вас есть сценарий foo.sh
с установленным исполняемым битом (x
). Этот файл содержит, например, следующее:
#!/bin/sh
# some script commands follow...:
# *snip*
Теперь в оболочке вы набираете:
> ./foo.sh
Edit: Пожалуйста, прочитайте также комментарии ниже после или до того, как вы прочитаете следующее! Как оказалось, я ошибался. Очевидно, что не оболочка передает сценарий целевому интерпретатору, а сама операционная система (ядро).
Помните, что вы набираете это внутри процесса shell (предположим, что это программа /bin/sh
). Поэтому этот ввод должен быть обработан этой программой. Она интерпретирует эту строку как команду, поскольку обнаруживает, что первое, что введено в строке, - это имя файла, который действительно существует и у которого установлен исполняемый бит(ы).
/bin/sh
затем начинает читать содержимое файла и обнаруживает шебанг (#!
) в самом начале файла. Для shell это маркер ("магическое число"), по которому он узнает, что файл содержит сценарий.
Теперь, как он узнает, на каком языке программирования написан сценарий? В конце концов, вы можете выполнять сценарии Bash, Perl, Python... Все, что shell пока знает, это то, что он смотрит на файл сценария (который является не двоичным, а текстовым файлом). Таким образом, он читает следующий ввод до первого перевода строки (что приведет к /bin/sh
, сравните с приведенным выше). Это интерпретатор, которому будет передан сценарий для выполнения. (В данном конкретном случае целевым интерпретатором является сам shell, поэтому ему не нужно вызывать новый shell для скрипта; он просто сам обрабатывает остальную часть файла скрипта).
Если бы скрипт предназначался, например, для /bin/perl
, все, что интерпретатору Perl (по желанию) нужно было бы сделать, это посмотреть, действительно ли в строке shebang упоминается интерпретатор Perl. Если нет, то интерпретатор Perl будет знать, что он не может выполнить этот сценарий. Если интерпретатор Perl действительно упоминается в строке shebang, он прочитает остальную часть файла сценария и выполнит его.