stringtranslate.com

Шебанг (Unix)

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

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

Строка shebang обычно игнорируется интерпретатором, поскольку символ «#» является маркером комментария во многих языках сценариев; некоторые языковые интерпретаторы, которые не используют решетку для начала комментариев, все равно могут игнорировать строку shebang в знак ее назначения. [9]

Синтаксис

Форма директивы интерпретатора shebang следующая: [8]

#! интерпретатор [ необязательный-аргумент ]

в котором интерпретатор — это путь к исполняемой программе. Пробел между #! и переводчик не является обязательным. До или после интерпретатора может быть любое количество пробелов или табуляций . Необязательный аргумент будет включать любые дополнительные пробелы до конца строки.

В Linux файл, указанный интерпретатором, может быть выполнен, если он имеет права на выполнение и является одним из следующих:

В Linux и Minix интерпретатором также может быть скрипт. Цепочка шебангов и оберток дает непосредственно исполняемый файл, который получает в качестве параметров встреченные скрипты в обратном порядке. Например, если файл /bin/A является исполняемым файлом в формате ELF , файл /bin/B содержит shebang #!/bin/A optparam, а файл /bin/C содержит shebang #!/bin/B, то выполнение файла /bin/C разрешается в /bin/B /bin/C, что в конечном итоге разрешается в /bin/A optparam /bin/B /bin/C.

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

Примеры

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

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

Цель

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

Сценарий оболочки Bourne , идентифицируемый путем some/path/to/foo , имеет начальную строку:

#!/бин/ш -х

и выполняется с параметрами bar и baz как

какой-то/путь/к/фу-бару баз

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

/bin/sh -x some/path/to/foo bar baz

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

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

#!/бин/котПривет, мир!

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

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

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

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

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

Аналогичная проблема существует и для оболочки POSIX , поскольку POSIX требовало, чтобы ее имя было только sh , но не задавало путь. Обычное значение — /bin/sh , но некоторые системы, такие как Solaris, имеют POSIX-совместимую оболочку по адресу /usr/xpg4/bin/sh . [12] Во многих системах Linux /bin/sh является жесткой или символической ссылкой на /bin/bash , оболочку Bourne Again (BASH). Использование синтаксиса, специфичного для bash, при сохранении shebang, указывающего на sh , также непереносимо. [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 и вызывает первый sh, найденный в $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) в env была добавлена ​​опция -S , поскольку она изменила режим чтения shebang на режим без разделения. Эта опция сообщает env о необходимости разделения самой строки. [17] Утилита GNU env , начиная с coreutils 8.30 (2018), также включает эту функцию. [18] Хотя использование этой опции смягчает проблему переносимости на стороне ядра при разделении, оно добавляет требование, чтобы env поддерживал это конкретное расширение.

Другая проблема — сценарии, содержащие символ возврата каретки сразу после строки шебанга, возможно, в результате редактирования в системе, использующей разрывы строк DOS , такой как Microsoft Windows . Некоторые системы интерпретируют символ возврата каретки как часть команды интерпретатора , что приводит к сообщению об ошибке. [19]

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

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

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

Этимология

Исполняемый файл, начинающийся с директивы интерпретатора, просто называется сценарием, которому часто предшествует имя или общая классификация предполагаемого интерпретатора. Название shebang для двух характерных символов могло произойти от неточного сокращения SHArp bang или haSH bang , относящегося к двум типичным для них именам Unix. Другая теория, касающаяся sh в shebang , заключается в том, что он взят из оболочки sh по умолчанию , обычно вызываемой с помощью shebang. [22] Это использование было актуальным к декабрю 1989 года, [23] и, вероятно, раньше.

История

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

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

В версии 8 улучшены сценарии оболочки.

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

От uucp, четверг, 10 января, 01:37:58, 1980 г.>От dmr, четверг, 10 января, 04:25:49, 1980, удален от исследований.Система была изменена таким образом, что если исполняемый файлначинается с магических символов #! , остальная часть строки понятнабыть именем интерпретатора исполняемого файла.Раньше (и фактически до сих пор) большую часть этой работы выполняла оболочка;он автоматически выполнил себя в текстовом файле с исполняемым режимомкогда имя текстового файла было введено как команда.Введение объекта в систему дает следующеепреимущества.1) Это делает сценарии оболочки более похожими на настоящие исполняемые файлы,потому что они могут быть предметом «исполнительного».2) Если вы наберете «ps» во время выполнения такой команды, это действительно так.имя появляется вместо «sh».Аналогично учет ведется на основании настоящего имени.3) Скрипты оболочки могут иметь set-user-ID . [а]4) Проще иметь альтернативные оболочки;например, если вам нравится Berkeley CSH, не может быть и речи окакая оболочка должна интерпретировать файл.5) Это позволит другим переводчикам более плавно вписаться.Чтобы воспользоваться этой замечательной возможностью,помещать #! /бин/ш в левом поле первой строки ваших сценариев оболочки.Пробелы после ! ОК. Используйте полный путь (поиск не производится).На данный момент вся строка ограничена 16 символами, ноэтот лимит будет повышен.

Функция безымянного сценария оболочки

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

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

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

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

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

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

Примечания

  1. ^ Функция setuid отключена в большинстве современных операционных систем после того, как стало известно, что состояние гонки может быть использовано для изменения сценария во время его обработки. [26]

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

  1. ^ «Расширенное руководство по написанию сценариев Bash: Глава 2. Начало с Ша-Банга» . Архивировано из оригинала 10 декабря 2019 года . Проверено 10 декабря 2019 г.
  2. Купер, Мендель (5 ноября 2010 г.). Расширенное руководство по написанию сценариев Bash, 5.3, том 1. lulu.com. п. 5. ISBN 978-1-4357-5218-4.
  3. ^ Макдональд, Мэтью (2011). HTML5: недостающее руководство. Севастополь, Калифорния: O'Reilly Media . п. 373. ИСБН 978-1-4493-0239-9.
  4. ^ Лутц, Марк (сентябрь 2009 г.). Изучение Python (4-е изд.). О'Рейли Медиа . п. 48. ИСБН 978-0-596-15806-4.
  5. Гелич, Гундаварам и Бирзниекс, Скотт, Шишир и Гюнтер (29 июля 2000 г.). Программирование CGI с использованием PERL (2-е изд.). О'Рейли Медиа . п. 358. ИСБН 978-1-56592-419-2.{{cite book}}: CS1 maint: несколько имен: список авторов ( ссылка )
  6. Ли Хетланд, Магнус (4 октября 2005 г.). Начало Python: от новичка до профессионала. Апресс. п. 21. ISBN 978-1-59059-519-0.
  7. Щитка, Джон (24 декабря 2002 г.). Руководство Linux+ по сертификации Linux. Курсовая технология. п. 353. ИСБН 978-0-619-13004-6.
  8. ^ ab "execve(2) — справочная страница Linux" . Проверено 21 октября 2010 г.
  9. ^ "СРФИ 22".
  10. ^ «Python — строка shebang Python3 не работает должным образом» .
  11. ^ Аб Машек, Свен (30 декабря 2010 г.). «Магия #!, подробности о механизме shebang/hash-bang: требуется пробел после #!?». www.in-ulm.de . Проверено 18 января 2024 г.
  12. ^ «Базовые спецификации открытой группы, выпуск 7» . 2008 год . Проверено 5 апреля 2010 г.
  13. ^ «pixelbeat.org: Распространенные ошибки сценариев оболочки» . Если это возможно, гораздо лучше тестировать сценарии непосредственно в POSIX-совместимой оболочке. Опции `bash --posix` недостаточно, поскольку она все еще принимает некоторые "башизмы".
  14. ^ «Глава 2. Язык команд оболочки», Базовые спецификации открытой группы (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. ^ "Вызов окружения". GNU Coreutils . Проверено 11 февраля 2020 г.
  19. ^ «Возврат каретки приводит к сбою bash» . 8 ноября 2013 г.
  20. ^ «Руководство GNU Autoconf v2.57, Глава 10: Программирование переносимой оболочки» . Архивировано из оригинала 18 января 2008 года . Проверено 14 мая 2020 г.
  21. ^ ab «Часто задаваемые вопросы UTF-8, UTF-16, UTF-32 и спецификация: может ли поток данных UTF-8 содержать символ спецификации (в форме UTF-8)? Если да, то могу ли я все еще предполагать оставшийся UTF-8 байты имеют обратный порядок?». Юникод . Проверено 10 ноября 2023 г.
  22. ^ "Запись в жаргонном файле для шебанга" . Catb.org . Проверено 16 июня 2010 г.
  23. ^ Уолл, Ларри . «Perl не распознавал сценарии setuid, в первой строке которых между именем интерпретатора и именем интерпретатора был пробел». ЮСЕТ .
  24. ^ ab «Архивные компакт-диски CSRG».
  25. ^ СИСТЕМА РАЗДЕЛЕНИЯ ВРЕМЕНИ UNIX: РУКОВОДСТВО ПРОГРАММИСТА UNIX (PDF) , том. 2А (Седьмое изд.), январь 1979 г.
  26. ^ Жиль. «Linux — Почему SUID отключен для сценариев оболочки, но не для двоичных файлов?». Обмен стеками информационной безопасности .
  27. ^ Ричи, Деннис. «Деннис Ричи и Хэш-Бэнг». Талисман.org . Проверено 3 декабря 2020 г.
  28. Рубини, Алессандро (31 декабря 1997 г.). «Игра с двоичными форматами». Linux-журнал . Проверено 1 января 2015 г.

Внешние ссылки