#!/ Bin/sh читается переводчиком?

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

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

#!/bin/bash

А в скриптах Python есть:

#!/bin/python

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

4 ответа

Решение

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

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

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

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

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

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

  • Если вы вызываете скрипт как исполняемый файл, например, запустив ./script.sh, система обращается к первой строке, чтобы увидеть, начинается ли с #!, за которым следует ноль или более пробелов, а затем команда. Если это так, он запускает эту команду с именем сценария в качестве аргумента. In this example, it runs /bin/sh script.sh (or, technically, /bin/sh ./script.sh).

  • If you invoke the script by explicitly calling the interpreter, the #! line is never consulted. So, if you run sh script.sh, the first line has no effect. Если script2.sh 's first line is #!/usr/games/nibbles, Бег sh script2.sh will not try to open the script in nibbles (but ./script2.sh будут).

You'll notice that in neither case does the script's extension (.sh), if it has one, impact how it is run. In a Unix-like system, this doesn't ordinarily affect how the script is run. On some other systems, like Windows, the #! shebang line might be ignored entirely by the system, and the extension might determine what runs the scripts. (This doesn't mean you need to give your scripts extensions, but it is one of the reasons why if you do, they should be correct.)

#! was chosen to serve this purpose precisely because # begins a comment. #! line is for the system, not the interpreter, and it should be ignored by the interpreter.

Shebang Line for Bash Scripts

You (originally) said you use #!/bin/sh за bash scripts. You should only do that if the script doesn't require any of bashРасширения-- sh должен быть в состоянии запустить скрипт. sh не всегда символическая ссылка на bash, Зачастую, в том числе во всех удаленно современных системах Debian и Ubuntu, sh символическая ссылка на dash,

Линия Шебанга для скриптов Python

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

/bin/sh read by the interpretor hello.py

/bin/sh попытается выполнить скрипт с именем readby 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 для файлов, которые не запускаются как сценарии

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

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

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

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

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

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

#!/usr/bin/env tee -a

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

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

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

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

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

#!/bin/sh

затем загрузчик программы получает указание запустить программу "/bin/sh", например, например, оболочку Bourne или совместимую оболочку, передавая "путь / к / вашему скрипту" в качестве первого аргумента.

Соответственно, скрипт называется с путем "путь к / python-скрипту" и начинается со следующей строки:

#!/bin/python

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

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

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

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

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

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

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

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

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

Когда вы делаете на Bash:

./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

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

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

Другие вопросы по тегам