Почему строка shebang всегда будет первой линией? - программирование
Подтвердить что ты не робот

Почему строка shebang всегда будет первой линией?

У меня есть простой скрипт на Perl, как показано ниже:

#!/usr/bin/perl

use strict;
use warnings;

print "hello world!\n";

Я могу выполнить этот скрипт, как показано ниже:

>temp.pl
hello world!
>

Если я добавлю несколько комментариев, как это:

#this script is just for test
#the shebang
#!/usr/bin/perl

use strict;
use warnings;

print "hello world!\n";

и когда я пытаюсь выполнить, это дает мне вывод, как показано ниже:

> temp.pl
use: Command not found.
use: Command not found.
print: Command not found.
> 

Дело в том, что линия Шебанга должна быть всегда наверху, несмотря ни на что. Кто-нибудь может объяснить, почему?

4b9b3361

Ответ 1

Shebang должен быть первой строкой, потому что он интерпретируется ядром , который смотрит на два байта в начале исполняемого файла. Если это #!, остальная часть строки интерпретируется как исполняемый файл для запуска и с файлом script, доступным для этой программы. (Детали немного меняются, но это изображение).

Так как ядро ​​будет смотреть только на первые два символа и не имеет понятия о дальнейших строках, вы должны поместить хеш-удар в строку 1.

Теперь, что произойдет, если ядро ​​не сможет выполнить файл, начинающийся с #!whatever? Оболочка, пытающаяся разблокировать исполняемый файл и быть информированным ядром о том, что он не может выполнить программу, в качестве последнего средства пытается интерпретировать содержимое файла как оболочку script. Поскольку оболочка не perl, вы получаете кучу ошибок, точно так же, как если бы вы пытались запустить

 sh < temp.pl

Ответ 2

В дополнение к приведенным выше объяснениям, которые подробно описаны здесь и здесь и здесь есть некоторые особенности о #! и Perl, которые еще не были упомянуты.

Perl читает строку #! и выполняет две вещи. Во-первых, если путь не похож на perl, он будет повторно использовать программу, используя это! Например...

#!/bin/sh

echo "Hello world!"

Будет выполняться правильно, если выполняется как perl /path/to/that/program. Я не знаю, по какой исторической причине Perl это делает, но это пригодится, когда вы тестируете несколько языков с помощью Test:: Harness.

Во-вторых, Perl находит любые переключатели в строке #! и применяет их так же, как если бы они были в командной строке. Вот почему #!/usr/bin/perl -w работает, чтобы включить предупреждения.

Стоит отметить, что в отличие от других частей обработки shebang, все это делается внутри Perl, а не Unix, и поэтому переносимо для Windows.

Еще одна заметка Perl + shebang - это безумие, которое вы можете найти в верхней части многих программ Perl.

#!/usr/bin/perl

eval 'exec /usr/bin/perl -w -S $0 ${1+"[email protected]"}'
    if 0; # not running under some shell

Иногда, в очень, очень, очень старых системах, #! не работает, и программа Perl выполняется оболочкой. eval заставляет оболочку сначала перенести файл с помощью Perl. Поскольку инструкции оболочки заканчиваются на новой строке, она не видит if 0. Perl видит if 0, поэтому он не выполняет eval. И Perl, и shell имеют синтаксически эквивалентные операторы eval, что делает работу взлома.

Ответ 3

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

Когда системе предлагается выполнить содержимое файла, либо с чем-то вроде .../path/to/bin/program, либо через аналогичный маршрут через PATH, он проверяет первые несколько байтов файла для поиска "магических чисел", которые показывают, какой тип файла он (вы можете заглянуть в этот процесс, используя команду file (1)). Если это скомпилированный двоичный файл, то он будет загружать и выполнять его соответствующим образом, и если эти первые два байта #!, он сделает "shebang-hack".

"shebang-hack" - это особый случай, используемый некоторыми оболочками (фактически, по существу, каждый, но скорее конвенция, чем требование), в котором оболочка читает оставшиеся байты до новой строки, интерпретирует эти как имя файла, а затем выполняет этот файл, предоставляя ему остальную часть текущего файла в качестве входного. Плюс некоторые детали, которые вы, вероятно, можете прочитать о в другом месте.

Некоторые (версии) оболочек позволят довольно длинные первые строки, некоторые из них допускают только короткие; некоторые из них допускают несколько аргументов, некоторые из них допускают только один.

Если файл не начинается с #!, но выглядит как текст, некоторые оболочки будут эвристически пытаться выполнить его в любом случае. Csh (если я правильно помню) берет пунт на том, что он является csh- script, и есть какой-то сложный и тайный случай, связанный с поведением некоторых оболочек, если первая строка пуста, а жизнь слишком короткая для запоминания.

Есть интересные и обширные детали (и точные, в том смысле, что они соответствуют моим воспоминаниям!) в Свен Маскек #! страница.

Ответ 4

По крайней мере, в POSIX-совместимых системах shebang используется, чтобы сообщить исполняемому загрузчику, что делать с текстовыми файлами, имеющими установленный бит.

Загрузчик знает, что делать с бинарными файлами, они начинаются с "магического числа", как правило, связанных с ELF в эти дни.

С другой стороны, текстовые файлы, которые не имеют shebang, выполняются оболочкой, совместимой с POSIX, доступной на компьютере, поэтому у вас есть эти сообщения об ошибках оболочки:

use: Command not found.
use: Command not found.
print: Command not found.

Когда исполняемый файл не должен интерпретироваться оболочкой, совместимой с POSIX, вам нужно сообщить загрузчику, какой интерпретатор использовать. Другие ОС, такие как Windows, выбирают расширение файла, чтобы понять это, но Unix не использует или не заботится о расширениях в этом конкретном случае. То, что он использует, - это shebang в первой строке, в котором указывается, какой интерпретатор команд использовать. Единственный недостаток заключается в том, что язык сценариев должен игнорировать эту первую строку. Это, надеюсь, случай, когда # является префикс строки комментария с большинством языков сценариев.

Несмотря на распространенное мнение, портативные скрипты вообще не должны иметь shebang. В частности, #!/bin/sh не рекомендуется для них.