Шебанг (Unix) - Shebang (Unix)

В вычисление, а Shebang последовательность символов, состоящая из символов числовой знак и восклицательный знак (#!) в начале сценарий. Его еще называют ша-бах,[1][2] хэшбэнг,[3][4] фунт-удар,[5][6] или же хэширование.[7]

Когда текстовый файл с shebang используется как исполняемый файл в Unix-подобный операционная система, загрузчик программ механизм анализирует остальную часть начальной строки файла как директива интерпретатора. Загрузчик выполняет указанный устный переводчик программа, передав ей в качестве аргумента путь, который изначально использовался при попытке запустить сценарий, чтобы программа могла использовать файл в качестве входных данных.[8] Например, если скрипт назван по пути путь / к / скрипту, и начинается со следующей строки, #! / bin / sh, то загрузчик программы получает указание запустить программу / bin / sh, прохождение путь / к / скрипту в качестве первого аргумента. Linux, такое поведение является результатом кода ядра и пользовательского пространства.[9]

Строка shebang обычно игнорируется интерпретатором, потому что символ "#" - это комментарий маркер на многих скриптовых языках; некоторые языковые интерпретаторы, которые не используют знак решетки для начала комментариев, могут игнорировать строку shebang, признавая ее назначение.[10]

Синтаксис

Форма шебанга директива интерпретатора как следует:[8]

#!устный переводчик [необязательный аргумент]

в котором устный переводчик является абсолютный путь в исполняемую программу.

Необязательный аргумент - это строка, представляющая единственный аргумент. Пробел после #! не является обязательным.

В Linux, файл, указанный устный переводчик может быть выполнен, если он имеет право на выполнение и содержит код, который ядро ​​может выполнить напрямую, если для него определена оболочка через sysctl (например, для выполнения Microsoft .EXE двоичные файлы с использованием вино ), или если он содержит шебанг. В Linux и Minix, интерпретатор также может быть скриптом. Цепочка shebangs и оберток дает непосредственно исполняемый файл, который получает встречающиеся скрипты в качестве параметров в обратном порядке. Например, если файл / bin / A это исполняемый файл в ELF формат, файл / bin / B содержит шебанг #! / bin / A optparam, и файл / bin / C содержит шебанг #! / bin / B, затем запускаем файл / bin / C решает / bin / B / bin / C, который, наконец, разрешается / bin / A optparam / bin / B / bin / C.

В Солярис- и Дарвин производные операционные системы (такие как macOS ), файл, указанный устный переводчик должен быть исполняемым двоичным файлом и не может быть скриптом.[11]

Примеры

Некоторые типичные строки шебанга:

  • #! / bin / sh - Запустите файл, используя Оболочка Борна или совместимая оболочка, предположительно находящаяся в каталоге / bin
  • #! / bin / bash - Запустите файл, используя Оболочка Bash
  • #! / usr / bin / env python3 - Выполнить с Python интерпретатор, используя путь поиска программы, чтобы найти его
  • #! / bin / false - Ничего не делать, но возвращать ненулевое значение статус выхода, что указывает на сбой. Используется для предотвращения автономного выполнения файла сценария, предназначенного для выполнения в определенном контексте, например, . команда из sh / bash, источник из csh / tcsh или в виде файла .profile, .cshrc или .login.

Строки Shebang могут включать определенные параметры, которые передаются интерпретатору. Однако реализации различаются поведением синтаксического анализа параметров; для переносимости следует указать только один параметр без каких-либо пробелов. Дополнительные инструкции по переносимости приведены ниже.

Цель

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

А Оболочка Борна скрипт, который определяется путем некоторые / путь / к / foo, имеет начальную строку,

#! / bin / sh -x

и выполняется с параметрами бар и баз в качестве

некоторые / путь / к / foo bar baz

дает результат, аналогичный фактическому выполнению вместо этого следующей командной строки:

/ bin / sh -x некоторые / путь / к / foo bar baz

Если / bin / sh определяет Оболочка Борна, то в конечном итоге все команды оболочки в файле некоторые / путь / к / foo выполняются с позиционными переменными $1 и $2 имеющий ценности бар и баз, соответственно. Кроме того, поскольку первоначальный числовой знак символ, используемый для введения комментариев в Оболочка Борна language (и на языках, понимаемых многими другими интерпретаторами) вся строка shebang игнорируется интерпретатором.

Однако интерпретатор должен игнорировать строку shebang; таким образом, сценарий, состоящий из следующих двух строк, просто повторяет обе линии к стандартный вывод при запуске:

#! / bin / catПривет, мир!

Сильные стороны

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

Портативность

Расположение программы

Shebangs необходимо указать абсолютные пути (или пути относительно текущего рабочего каталога) к системным исполняемым файлам; это может вызвать проблемы в системах с нестандартной структурой файловой системы. Даже когда в системах используются довольно стандартные пути, вполне возможно, что варианты одной и той же операционной системы могут иметь разные местоположения для желаемого интерпретатора. Python, например, может быть в / usr / bin / python3, / USR / местные / бен / python3, или даже что-то вроде / главная / имя пользователя / bin / python3 если установлен обычным пользователем.

Аналогичная проблема существует для Оболочка POSIX, поскольку POSIX требовал, чтобы его имя было ш, но не указывал путь. Общая ценность / bin / sh, но некоторые системы, такие как Solaris, имеют POSIX-совместимую оболочку по адресу / usr / xpg4 / bin / sh.[12] Во многих Linux системы, / bin / sh сложно или символическая ссылка к / bin / bash, то Bourne Again оболочка (БАШ). Использование синтаксиса, специфичного для bash, при сохранении shebang, указывающего на ш также не переносится.[13]

Из-за этого иногда требуется отредактировать строку shebang после копирования сценарий с одного компьютера на другой, потому что путь, который был закодирован в сценарии, может не применяться на новой машине, в зависимости от согласованности в прошлом соглашении о размещении интерпретатора. По этой причине и потому что POSIX не стандартизирует имена путей, POSIX не стандартизирует эту функцию.[14] В GNU Autoconf инструмент может проверить поддержку системы с помощью макроса AC_SYS_INTERPRETER.[15]

Часто программа / usr / bin / env можно использовать для обхода этого ограничения путем введения уровня косвенное обращение. #! следует / usr / bin / env, за которым следует желаемая команда без полного пути, как в этом примере:

#! / usr / bin / env sh

В основном это работает, потому что путь / usr / bin / env обычно используется для env утилита, и она вызывает первую ш найдено в пользователе $ PATH обычно / bin / sh.

Это все еще имеет некоторые проблемы с переносимостью OpenServer 5.0.6 и Unicos 9.0.2, в которых есть только / bin / env и нет / usr / bin / env.

Интерпретация персонажей

Другой проблемой переносимости является интерпретация аргументов команды. Некоторые системы, включая Linux, не разделяют аргументы;[16] например, при запуске скрипта с первой строкой вида,

#! / usr / bin / env python3 -c

весь текст после первого пробела рассматривается как один аргумент, то есть python3 -c будет передан как один аргумент в / usr / bin / env, а не два аргумента. Cygwin тоже так себя ведет.

Вызовы сложных интерпретаторов возможны за счет использования дополнительных обертка. FreeBSD 6.0 (2005) представила -S вариант для своего env поскольку это изменило поведение чтения shebang на неразрывное. Эта опция сообщает env чтобы разбить саму строку.[17] GNU env Утилита, начиная с coreutil 8.30 (2018), также включает эту функцию.[18] Хотя использование этой опции уменьшает проблему переносимости на стороне ядра с разделением, она добавляет требование, что env поддерживает это конкретное расширение.

Другая проблема - скрипты, содержащие возврат каретки символ сразу после строки shebang, возможно, в результате редактирования в системе, использующей DOS разрывы строк, Такие как Майкрософт Виндоус. Некоторые системы интерпретируют символ возврата каретки как часть устный переводчик команда, в результате чего появляется сообщение об ошибке.[19]

Магическое число

Шебанг на самом деле является понятным для человека экземпляром магическое число в исполняемом файле, магическая байтовая строка 0x23 0x21, двухсимвольная кодировка в ASCII из #!. Это магическое число определяется символом "exec "семейство функций, которые определяют, является ли файл сценарием или исполняемым двоичным файлом. Присутствие shebang приведет к выполнению указанного исполняемого файла, обычно интерпретатора для языка сценария.[20] что некоторые старые версии Unix ожидают, что после обычного shebang следует пробел и косая черта (#! /), но это кажется неправдой;[21][нужна цитата ] скорее, пробелы после шебанга традиционно допускались и иногда документировались с пробелом (см. электронное письмо 1980 г. в история раздел ниже).

Символы shebang представлены теми же двумя байтами в расширенный ASCII кодировки, в том числе UTF-8, который обычно используется для скриптов и других текстовых файлов в текущих Unix-подобных системах. Однако файлы UTF-8 могут начинаться с необязательного метка порядка байтов (Спецификация); если функция "exec" специально обнаруживает байты 0x23 и 0x21, то наличие спецификации (0xEF 0xBB 0xBF) перед shebang предотвратит выполнение интерпретатора скрипта. Некоторые специалисты рекомендуют не использовать знак порядка байтов в POSIX (Unix-подобные) скрипты,[22] по этой причине, а также для более широкого взаимодействия и философских соображений. Кроме того, в UTF-8 не требуется метка порядка байтов, поскольку эта кодировка не имеет порядок байтов вопросы; он служит только для идентификации кодировки как UTF-8.

Этимология

Исполняемый файл, начинающийся с директивы интерпретатора, просто называется сценарием, часто перед ним указывается имя или общая классификация предполагаемого интерпретатора. Название Shebang поскольку два отличительных символа могли произойти из-за неточного сокращение из Острый хлопнуть или же хаШ бац, ссылаясь на два типичных имени Unix для них. Еще одна теория о ш в Shebang в том, что это из оболочки по умолчанию ш, обычно вызывается с помощью shebang.[23] Это использование было актуальным к декабрю 1989 г.,[24] и, наверное, раньше.

История

Шебанг был представлен Деннис Ричи между Выпуск 7 и 8 в Bell Laboratories. Он также был добавлен в BSD релизы от Berkeley's Computer Science Research (присутствуют на 2.8BSD[25] и активируется по умолчанию 4.2BSD). Поскольку AT&T Bell Laboratories Edition 8 Unix и более поздние версии не были выпущены для широкой публики, первое широко известное появление этой функции было на BSD.

Отсутствие директивы интерпретатора, но поддержка сценариев оболочки, очевидно в документации от Версия 7 Unix в 1979 г.,[26] который описывает вместо этого средство оболочки Bourne, где файлы с разрешением на выполнение будут обрабатываться специально оболочкой, которая (иногда в зависимости от начальных символов в сценарии, таких как ":" или "#") порождает подоболочку, которая будет интерпретировать и запустите команды, содержащиеся в файле. В этой модели сценарии будут вести себя как другие команды только в том случае, если они вызываются из оболочки Bourne. Попытка выполнить такой файл напрямую через собственный exec () системная ловушка не сработает, не позволяя сценариям вести себя как обычные системные команды.

В более поздних версиях Unix-подобных систем это несоответствие было устранено. Деннис Ричи представила поддержку ядра для директив интерпретатора в январе 1980 года для Версия 8 Unix, со следующим описанием:[25]

От uucp Чт 10 января, 01:37:58 1980

> От dmr Чт, 10 января, 04:25:49 1980 г. удалено из исследования

Система была изменена таким образом, что если исполняемый файл начинается с магических символов #! остальная часть строки понимается как имя интерпретатора для исполняемого файла. Раньше (и на самом деле до сих пор) оболочка выполняла большую часть этой работы; она автоматически выполняла себя для текстового файла в исполняемом режиме, когда имя текстового файла было вводится как команда. Включение объекта в систему дает следующие преимущества.

1) Это делает сценарии оболочки более похожими на настоящие исполняемые файлы, потому что они могут быть предметом 'exec'.

2) Если вы введете "ps" во время выполнения такой команды, вместо "sh" появится ее настоящее имя. Точно так же учет ведется на основе настоящего имени.

3) В сценариях оболочки можно указать идентификатор пользователя.

4) Проще иметь альтернативные оболочки, например. Если вам нравится Berkeley csh, не возникает вопросов, какая оболочка должна интерпретировать файл.

5) Это позволит другим переводчикам более плавно вписаться в работу.

Чтобы воспользоваться этой замечательной возможностью, поставьте

  #! / bin / sh

на левом поле первой строки ваших сценариев оболочки. ОК. Используйте полный путь (поиск не производится). На данный момент вся строка ограничена 16 символами, но этот предел будет увеличен.

Однако создатель функции не дал ей названия:[27]

От: "Ричи, Деннис М (Деннис) ** CTR **"  Кому: <[отредактировано] @ talisman.org> Дата: четверг, 19 ноября 2009 г., 18:37:37 -0600 Тема: RE : Как -вы- называете свою линию #! ? Я не могу вспомнить, чтобы мы когда-либо давали ему собственное имя. Было довольно поздно, что оно вошло - я думаю, что я получил эту идею от кого-то на одной из конференций UCB в Беркли, Unix; Возможно, я был одним из первых, кто его установил, но это была идея, которую я почерпнул откуда-то еще. Что касается названия: вероятно, что-то описательное, вроде "hash-bang", хотя оно имеет специфически британский оттенок, но в любом случае я этого не делаю. Я особо не вспоминаю использование клички питомца для строительства.

Поддержка ядром директив интерпретатора распространяется на другие версии Unix, и одну современную реализацию можно увидеть в исходном коде ядра Linux в fs / binfmt_script.c.[28]

Этот механизм позволяет использовать сценарии практически в любом контексте, в котором могут быть обычные скомпилированные программы, в том числе как полные системные программы и даже как интерпретаторы других сценариев. Однако в качестве предостережения некоторые ранние версии поддержки ядра ограничивали длину директивы интерпретатора примерно до 32 символов (всего 16 в первой реализации), не могли бы отделить имя интерпретатора от любых параметров в директиве или имели другие причуды. . Кроме того, некоторые современные системы позволяют ограничивать или отключать весь механизм в целях безопасности (например, поддержка set-user-id отключена для скриптов во многих системах).

Обратите внимание, что даже в системах с полной поддержкой ядра для #! магическое число, некоторые сценарии, в которых отсутствуют директивы интерпретатора (хотя обычно все еще требуют разрешения на выполнение), по-прежнему могут выполняться благодаря устаревшей обработке сценариев оболочки Bourne, все еще присутствующей во многих ее современных потомках. Затем сценарии интерпретируются оболочкой пользователя по умолчанию.

Смотрите также

Рекомендации

  1. ^ "Advanced Bash Scripting Guide: Глава 2. Начиная с Sha-Bang". В архиве с оригинала 10 декабря 2019 г.. Получено 10 декабря 2019.
  2. ^ Купер, Мендель (5 ноября 2010 г.). Advanced Bash Scripting Guide 5.3 Том 1. lulu.com. п. 5. ISBN  978-1-4357-5218-4.
  3. ^ Макдональд, Мэтью (2011). HTML5: отсутствующее руководство. Севастополь, Калифорния: O'Reilly Media. п. 373. ISBN  978-1-4493-0239-9.
  4. ^ Лутц, Марк (сентябрь 2009 г.). Изучение Python (4-е изд.). O'Reilly Media. п. 48. ISBN  978-0-596-15806-4.
  5. ^ Гелих, Гундаварам и Бирзниекс, Скотт, Шишир и Гюнтер (29 июля 2000 г.). Программирование CGI с помощью PERL (2-е изд.). O'Reilly Media. п.358. ISBN  978-1-56592-419-2.
  6. ^ Ли Хетланд, Магнус (4 октября 2005 г.). Начиная с Python: от новичка до профессионала. Апресс. п. 21. ISBN  978-1-59059-519-0.
  7. ^ Щитка, Джон (24 декабря 2002 г.). Linux + Руководство по сертификации Linux. Курсовая технология. п. 353. ISBN  978-0-619-13004-6.
  8. ^ а б "execve (2) - страница руководства Linux". Получено 21 октября 2010.
  9. ^ Корбет, Джонатан. "Дело о крупногабаритном шебанге". LWN.net.
  10. ^ «СРФИ 22».
  11. ^ https://stackoverflow.com/questions/45444823/python3-shebang-line-not-working-as-expected
  12. ^ "Базовые спецификации Open Group, выпуск 7". 2008. Получено 5 апреля 2010.
  13. ^ "pixelbeat.org: Распространенные ошибки сценариев оболочки". Если возможно, гораздо лучше тестировать сценарии непосредственно в оболочке, совместимой с POSIX. Опция `bash --posix` недостаточна, поскольку она все еще принимает некоторые` `башизмы ''
  14. ^ «Глава 2. Командный язык оболочки», Базовые спецификации Open Group (IEEE Std 1003.1-2017) (Выпуск 7-е изд.), IEEE, 2018 [2008], Если первая строка файла команд оболочки начинается с символов «#!», Результаты не указаны.
  15. ^ Autoconf, Фонд свободного программного обеспечения, Макрос: AC_SYS_INTERPRETER: проверьте, поддерживает ли система запуск сценариев со строкой вида «#! / Bin / sh», чтобы выбрать интерпретатор, который будет использоваться для сценария.
  16. ^ "/ usr / bin / env поведение". Mail-index.netbsd.org. 9 ноября 2008 г.. Получено 18 ноября 2010.
  17. ^ env (1) – FreeBSD Общие команды Руководство
  18. ^ "вызов env". GNU Coreutils. Получено 11 февраля 2020.
  19. ^ "Возврат каретки приводит к сбою bash". 8 ноября 2013 г.
  20. ^ "Руководство GNU Autoconf v2.57, Глава 10: Программирование переносимой оболочки". Архивировано из оригинал 18 января 2008 г.. Получено 14 мая 2020.
  21. ^ "Магия #!, Подробности о механизме shebang / hash-bang в различных версиях Unix". Получено 14 мая 2020.
  22. ^ «Часто задаваемые вопросы - UTF-8, UTF-16, UTF-32 и спецификация: может ли поток данных UTF-8 содержать символ спецификации (в форме UTF-8)? Если да, могу ли я предположить, что оставшиеся байты UTF-8 в порядке прямого байта? ". Получено 4 января 2009.
  23. ^ "Запись жаргонного файла для shebang". Catb.org. Получено 16 июн 2010.
  24. ^ Уолл, Ларри. "Perl не находил скрипты setuid, в которых в первой строке между shebang и именем интерпретатора был пробел". USENET.
  25. ^ а б "Архивные компакт-диски CSRG".
  26. ^ СИСТЕМА РАСПРЕДЕЛЕНИЯ ВРЕМЕНИ UNIX: РУКОВОДСТВО ПРОГРАММАТОРА UNIX (PDF), (Седьмое изд.), Январь 1979 г.
  27. ^ Ричи, Деннис. "Деннис Ричи и Hash-Bang". Talisman.org. Получено 3 декабря 2020.
  28. ^ Рубини, Алессандро (31 декабря 1997 г.). «Игра с двоичными форматами». Linux журнал. Получено 1 января 2015.

внешняя ссылка