Вопрос Является ли #! / Bin / sh интерпретатором?


В bash или sh, Я думаю, что все, что начинается с # это комментарий,

Но в bash скрипты, которые мы пишем:

#!/bin/bash

А в сценариях Python есть:

#!/bin/python

Означает ли это, что # сам по себе является комментарием, тогда как #! не является?


61
2018-01-09 06:04


происхождения


И как только вы начнете просматривать профили Apparmor, вы увидите #include, Там тоже # не является комментарием.
@ vasa1 Но ключевой момент, который часто не оценивается по линиям hashbang в начале скриптов оболочки, заключается в том, что Oни находятся Комментарии, - Eliah Kagan


ответы:


#! используется линия до сценарий запускается, а затем игнорируется когда скрипт запускается.

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

Строка, начинающаяся с #! так же, как и любая другая строка, которая начинается с #, Это верно, если #! это первая строка файла или где-либо еще. #!/bin/sh  имеет эффект, но он не считывается самим интерпретатором,

# не является комментарием на всех языках программирования, но, как вы знаете, это комментарий в оболочках в стиле Бурна, включая sh а также bash (а также большинство оболочек не-борновского типа, например csh). Это также комментарий в Python, И это комментарий в различных конфигурационных файлах, которые вообще не являются скриптами (например, /etc/fstab).

Предположим, что сценарий оболочки начинается с #!/bin/sh, Это комментарий, и интерпретатор (оболочка) игнорирует все на линии после # персонаж.

Цель #! строка не должна предоставлять информацию интерпретатору. Цель #! строка должна сообщить операционной системе (или какой-либо процесс запускает интерпретатор) что использовать в качестве переводчика,

  • Если вы вызываете скрипт как исполняемый файл, например, запустив ./script.sh, система проверяет первую строку, чтобы узнать, начинается ли она с #!, за которым следует ноль или более пробелов, за которым следует команда. Если это так, он запускает эту команду с именем скрипта в качестве аргумента. В этом примере он запускается /bin/sh script.sh (или, технически, /bin/sh ./script.sh).

  • Если вы вызываете скрипт, явно вызывая интерпретатор, #! линия никогда не консультируется. Итак, если вы запустите sh script.sh, первая строка не действует. Если script2.shПервая строка #!/usr/games/nibbles, Бег sh script2.sh не будет пытаться открыть сценарий в nibbles (но ./script2.sh будем).

Вы заметите, что ни в одном случае расширение скрипта (.sh), если он имеет один, влияют на то, как он выполняется. В Unix-подобной системе это обычно не влияет на запуск сценария. В некоторых других системах, таких как Windows, #! строка shebang может быть полностью проигнорирована системой, а расширение может определять, что запускает скрипты. (Это не означает, что вам нужно дать свои расширения для скриптов, но это одна из причин, почему, если вы это делаете, они должны быть правильными.)

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

Линия Shebang для скриптов Bash

Вы (изначально) сказали, что используете #!/bin/shдля bash скрипты. Вы должны делать это только в том случае, если скрипт не требует какого-либо из bashрасширения -sh должен иметь возможность запускать скрипт. sh не всегда является символической ссылкой на bash, Часто, включая все удаленные системы Debian и Ubuntu, sh символическая ссылка на dash,

Линия Shebang для скриптов Python

Вы также сказали (в первой версии своего вопроса перед редактированием), что вы запускаете свои скрипты Python с помощью #!/bin/sh read by the interpretor, Если вы имеете в виду это буквально, то вы обязательно должны прекратить это делать. Если hello.py начинается с этой строки, работает ./hello.py выполняет:

/bin/sh read by the interpretor hello.py

/bin/sh попытается выполнить скрипт под названием read (с by the interpretor hello.py как его аргументы), read (надеюсь) не будет найден, и ваш скрипт Python никогда не увидит интерпретатор Python.

Если вы делаете эту ошибку, но не имеете проблемы, которую я описываю, вы, вероятно, ссылаетесь на свои скрипты на Python, явно указывая интерпретатор (например, python hello.py), в результате чего первая строка игнорируется. Когда вы распространяете свои скрипты другим или используете их долгое время позже, может быть неясно, что это необходимо для их работы. Лучше всего их исправить. Или, по крайней мере, удалить первую строку целиком, чтобы, когда они не запускались с ./ сообщение об ошибке будет иметь смысл.

Для скриптов Python, если вы знаете, где интерпретатор Python (или будет), вы можете написать #! строка так же:

#!/usr/bin/python

Или, если это сценарий Python 3, вы должны указать python3, поскольку python почти всегда Python 2:

#!/usr/bin/python3

Однако проблема заключается в том, что /bin/sh предполагается всегда существовать, и /bin/bash почти всегда существует в системах, где bash поставляется с ОС, Python может существовать в самых разных местах.

Поэтому многие программисты Python используют это вместо этого:

#!/usr/bin/env python

(Или #!/usr/bin/env python3 для Python 3.)

Это заставляет сценарий полагаться на env находясь в «правильном месте» вместо того, чтобы полагаться на python находясь в нужном месте. Это хорошо, потому что:

  • env почти всегда находится в /usr/bin,
  • В большинстве систем, в зависимости от того, что python  должен запустите свой скрипт, который появляется первым в PATH, начало hello.py с #!/usr/bin/env python делать ./hello.py бег /usr/bin/env python hello.py, который (фактически) эквивалентен запуску python hello.py,

Причина, по которой вы не можете использовать #!python в том, что:

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

Иногда Python или другой скрипт, который не является скриптом оболочки, будет иметь строку shebang, начиная с #!/bin/sh ... где ... это другой код. Иногда это правильно, потому что есть несколько способов вызвать совместимую с Bourne оболочку (sh) с аргументами, чтобы заставить его вызвать интерпретатор Python. (Один из аргументов, вероятно, будет содержать python.) Однако для большинства целей, #!/usr/bin/env python проще, элегантнее и, скорее всего, будет работать так, как вы хотите.

Линии Шебанга на других языках

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

На некоторых языках программирования, # обычно не является комментарием, но в качестве частного случая первая строка игнорируется, если она начинается с #!, Это облегчает использование #! синтаксис, хотя # в противном случае не делает строкой комментарий.

Shebang Lines для файлов, которые не запускаются как скрипты

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

Некоторые приложения используют это поведение намеренно. Например, в VMware, .vmx файлы определяют виртуальные машины. Вы можете «запустить» виртуальную машину, как если бы это был скрипт, потому что эти файлы отмечены как исполняемые и имеют строку shebang, заставляющую их открываться в утилите VMware.

Shebang Lines для файлов, которые не работают как скрипты, но действуют как скрипты в любом случае

rm удаляет файлы. Это не скриптовый язык. Однако файл, который запускается #!/bin/rm и отмеченный исполняемый файл может быть запущен, а когда вы запустите его, rm вызывается на нем, удаляя его.

Это часто концептуализируется как «файл удаляет себя». Но файл вообще не работает. Это больше похоже на ситуацию, описанную выше для .vmx файлы.

Тем не менее, поскольку #! line упрощает запуск упрощенной команды (включая аргументы командной строки), вы можете выполнить некоторые сценарии таким образом. В качестве простого примера «сценария» сложнее, чем #!/bin/rm, рассматривать:

#!/usr/bin/env tee -a

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

Полезно? Не очень. Концептуально интересно? Полностью! Да. (В некотором роде.)

Концептуально похожие концепции программирования / сценариев (просто для удовольствия)


93
2018-01-09 07:30



Отлично! Надеюсь, это не просто c / p, хотя;) - Rinzwind
иногда мне жаль, что я не мог бы продвигать не один раз @EliahKagan - Rinzwind
Если это всегда игнорируется, то что такое Pythons -x флаг делать? - gerrit
@gerrit Хороший вопрос. На любом языке, где intrereter / компилятор сообщает сообщения с номерами строк, содержание игнорируются, но строки комментариев все еще подсчитаны, Добавление комментария или пустой строки до того, как строка кода по-прежнему приведет к тому, что строка кода имеет номер строки, увеличенный. -x "пропустить [s] первую строку ..." вторая строка пронумерована 1 вместо 2, 3-я строка 2 вместо 3и т. д. Вот почему вы не должны использовать этот флаг. ;) -x для сценариев на не-Unix-подобных операционных системах, которые имеют синтаксис типа shebang, не начиная с # (таким образом, не комментарий Python). - Eliah Kagan
В Perl, если интерпретатор запускается напрямую (perl script.pl против ./script.pl), то переводчик будем прочитайте строку shebang для разбора флагов, таких как -w, Однако не рекомендуется полагаться на эту функцию. - OrangeDog


Шебангом является последовательность символов, состоящая из знака числа знаков и восклицательного знака (например, «#!»), Когда он встречается как начальные два символа в начальной строке скрипта.

В операционных системах * nix, когда запускается скрипт, начинающийся с shebang, загрузчик программ анализирует остальную часть начальной строки сценария как директиву интерпретатора; вместо этого выполняется указанная программа интерпретатора, передавая ей в качестве аргумента путь, который изначально использовался при попытке запустить скрипт. Например, если сценарий имеет имя с путём «путь / к / ваш-скрипт» и начинается со следующей строки:

#!/bin/sh

то загрузчику программы будет предложено запустить программу «/ bin / sh», а не e.g. оболочкой Bourne или совместимой оболочкой, передавая «путь / в / ваш-скрипт» в качестве первого аргумента.

Соответственно, это сценарий с именем path / to / python-script и начинается со следующей строки:

#!/bin/python

то загруженной программе предлагается запустить программу «/ bin / python», а не, например, Python, передавая «путь / в / питон-скрипт» в качестве первого аргумента.

Короче говоря, «#» будет комментировать строку, а последовательность символов «#!» как первые два символа на начальной строке скрипта имеет значение, описанное выше.

Подробнее см. Почему некоторые скрипты начинаются с #! ...?

Источник: Некоторые разделы этого ответа получены (с небольшими изменениями) из Шебанг (Unix) на Английский Википедия (от Участник Wikipedia). Эта статья лицензирован под CC-BY-SA 3.0, то же, что и пользовательский контент здесь, на AU, поэтому этот вывод разрешен с атрибуцией.


7
2018-01-09 06:57





#! называется shebang когда это происходит как начальные два символа в начальной строке скрипта. Он используется в сценариях для указания интерпретатора для выполнения. shebang для операционной системы (ядра), а не для оболочки; поэтому он не будет интерпретироваться как комментарий.

Предоставлено:  http://en.wikipedia.org/wiki/Shebang_%28Unix%29 

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

Подробная информация:  http://wiki.bash-hackers.org/scripting/basics#the_shebang


4
2018-01-09 06:34





Нет, он используется только exec системный вызов ядра Linux и рассматривается как комментарий интерпретатора

Когда вы делаете бит:

./something

в Linux это вызывает exec системный вызов с помощью пути ./something,

Эта строка ядра вызывается в файле, переданном exec: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm-> buf [0]! = '#') || (bprm-> buf [1]! = '!'))

Это считывает первые байты файла и сравнивает их с #!,

Если это так, то остальная часть строки анализируется ядром Linux, что делает другой вызов exec с помощью пути /usr/bin/env python и текущий файл в качестве первого аргумента:

/usr/bin/env python /path/to/script.py

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

И да, вы можете сделать бесконечный цикл с:

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bash распознает ошибку:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#! просто случается, что он читается человеком, но это не требуется.

Если файл начался с разных байтов, то exec системный вызов будет использовать другой обработчик. Другой самый важный встроенный обработчик - для исполняемых файлов ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 который проверяет байты 7f 45 4c 46 (который также, по-видимому, является человеком, читаемым для .ELF). Это считывает файл ELF, правильно помещает его в память и запускает с ним новый процесс. Смотрите также: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861

Наконец, вы можете добавить своих собственных обработчиков shebang с помощью binfmt_misc механизм. Например, вы можете добавить пользовательский обработчик для .jar файлы, Этот механизм даже поддерживает обработчики с расширением файла. Другое приложение прозрачно запускать исполняемые файлы другой архитектуры с QEMU,

Я не думаю, что POSIX указывает на shebangs: https://unix.stackexchange.com/a/346214/32558 , хотя он упоминает в разделах обоснования и в форме «если исполняемые скрипты поддерживаются системой, что-то может случиться».


0
2018-03-28 13:30