Кто может сказать мне, почему этот вопрос закрыт, «не связан с программированием или разработкой программного обеспечения»?
tarrsalah
1
Я согласен, что это не вне темы, но, вероятно, это дубликат нескольких других вопросов, таких как этот .
Кит Томпсон
16
Этот вопрос не должен быть помечен как не по теме. Нужно только 5 человек с оценкой выше 3000, чтобы пометить его как «по теме», и его можно открыть заново. Это вопрос - конкретно о программировании.
Выполнение команды сквозной /usr/bin/envимеет преимущество ищет то , что по умолчанию версия программы находится в текущем окр ironment.
Таким образом, вам не нужно искать его в определенном месте в системе, поскольку эти пути могут находиться в разных местах в разных системах. Пока он на вашем пути, он его найдет.
Одним из недостатков является то, что вы не сможете передать более одного аргумента (например, вы не сможете писать /usr/bin/env awk -f), если вы хотите поддерживать Linux, поскольку POSIX неопределен в отношении того, как должна интерпретироваться строка, и Linux интерпретирует все после первого пространство для обозначения одного аргумента. Вы можете использовать /usr/bin/env -Sв некоторых версиях, envчтобы обойти это, но тогда сценарий станет еще менее переносимым и сломается на довольно недавних системах (например, даже Ubuntu 16.04, если не позже).
Другим недостатком является то, что, поскольку вы не вызываете явный исполняемый файл, у него есть вероятность ошибок и проблем с безопасностью многопользовательских систем (например, если кому-то удалось получить вызываемый файл bashна вашем пути).
#!/usr/bin/env bash #lends you some flexibility on different systems#!/usr/bin/bash #gives you explicit control on a given system of what executable is called
В некоторых ситуациях первое может быть предпочтительным (например, запуск сценариев Python с несколькими версиями Python без необходимости переделки исполняемой строки). Но в ситуациях, когда безопасность находится в центре внимания, последнее предпочтительнее, так как оно ограничивает возможности внедрения кода.
Другим недостатком является то, что вы не можете передать дополнительный аргумент интерпретатору.
Кит Томпсон
1
@KeithThompson: Неверная информация. Вы можете передать параметры соответствующему интерпретатору, используя / usr / bin / env!
Гаурав Агарвал
4
@GauravAgarwal: Не в моей системе. Сценарий , содержащий только эту одну строку: #!/usr/bin/env echo Helloжалуется: /usr/bin/env: echo Hello: No such file or directory. По-видимому, это рассматривается echo Helloкак один аргумент /usr/bin/env.
Кит Томпсон
1
@ AndréLaszlo: envкоманда, безусловно, позволяет передавать аргументы команде. Проблема заключается в семантике #!строки, и это зависит от ядра. Последние ядра Linux допускают такие вещи, как #!/usr/bin/env command argsстарые ядра Linux и другие системы.
Кит Томпсон
1
Почему в блоке кода есть обратные пометки? Разве они не должны быть удалены?
Бенджамин В.
64
Использование #!/usr/bin/env NAMEзаставляет оболочку искать первое совпадение NAME в переменной окружения $ PATH. Это может быть полезно, если вы не знаете об абсолютном пути или не хотите его искать.
По крайней мере, вы должны знать, где находится env :).
ᐅ devrimbaris
1
Отличный ответ. Кратко объясняет, что делает env shebang, вместо того, чтобы сказать «выбирает программу на основе конфигурации вашей системы»
De Novo
13
Вместо того, чтобы явно определять путь к интерпретатору, как /usr/bin/bash/при использовании команды env, интерпретатор ищется и запускается оттуда, где он был впервые найден. Это имеет как плюсы, так и минусы
В большинстве систем они будут одинаковыми, но это зависит от расположения исполняемых файлов bash и env. Не уверен, как это повлияет на переменные среды, хотя.
Safay
2
«Можно указать переводчика без использования env, указав полный путь к интерпретатору. Проблема заключается в том, что в разных компьютерных системах точный путь может быть разным. Вместо этого при использовании env ищется и располагается переводчик в время выполнения сценария. Это делает сценарий более переносимым, но также увеличивает риск выбора неправильного интерпретатора, поскольку он ищет совпадения в каждом каталоге на исполняемом пути поиска. Он также страдает от той же проблемы, что путь к двоичному файлу env также может быть разным для каждой машины. "- Википедия
Майк Кларк
10
Если сценарии оболочки начинаются с #!/bin/bash, они всегда будут работать с bashс /bin. Если они однако начать с #!/usr/bin/env bash, они будут искать bashв $PATHи затем начать с первыми они могут найти.
Почему это было бы полезно? Предположим, вы хотите запустить bashсценарии, для которых требуется bash 4.x или новее, но в вашей системе установлена только bash3.x, и в настоящее время ваш дистрибутив не предлагает более новую версию, или вы не являетесь администратором и не можете изменить то, что установлено в этой системе. ,
Конечно, вы можете скачать исходный код bash и создать свой собственный bash с нуля, разместив его, ~/binнапример. И вы также можете изменить свою $PATHпеременную в своем .bash_profileфайле, чтобы включить ~/binв качестве первой записи ( PATH=$HOME/bin:$PATHпоскольку ~не будет расширяться в $PATH). Если вы сейчас позвоните bash, оболочка сначала будет искать его $PATHпо порядку, поэтому она начинается с того места ~/bin, где она найдет ваш bash. То же самое происходит, если скрипты ищут для bashиспользования #!/usr/bin/env bash, поэтому эти скрипты теперь будут работать в вашей системе с использованием вашей пользовательской bashсборки.
Недостатком является то, что это может привести к неожиданному поведению, например, один и тот же сценарий на одном и том же компьютере может работать с разными интерпретаторами для разных сред или пользователей с разными путями поиска, вызывая все виды головной боли.
Самым большим недостатком envявляется то, что некоторые системы допускают только один аргумент, поэтому вы не можете сделать это #!/usr/bin/env <interpreter> <arg>, так как системы будут рассматривать <interpreter> <arg>как один аргумент (они будут обрабатывать его, как если бы выражение было заключено в кавычки) и, таким образом, envбудут искать интерпретатор с именем <interpreter> <arg>. Обратите внимание, что это не проблема самой envкоманды, которая всегда позволяла передавать несколько параметров, но с помощью анализатора shebang системы, которая анализирует эту строку еще до вызова env. Между тем, это было исправлено в большинстве систем, но если ваш скрипт хочет быть сверхпортативным, вы не можете полагаться, что это было исправлено в системе, которую вы будете использовать.
Он может даже иметь последствия для безопасности, например, если sudoон не был настроен для очистки окружающей среды или $PATHбыл исключен из очистки. Позвольте мне продемонстрировать это:
Обычно /binэто хорошо защищенное место, только там rootможно что-то изменить. Ваш домашний каталог, однако, не любая программа, которую вы запускаете, может внести в нее изменения. Это означает, что вредоносный код может поместить фальшивку bashв какой-то скрытый каталог, изменить его, .bash_profileчтобы включить этот каталог в свой $PATH, так что все используемые скрипты в #!/usr/bin/env bashконечном итоге будут работать с этой фальшивкой bash. Если sudoдержится $PATH, у вас большие проблемы.
Например, рассмотрим инструмент, создающий файл ~/.evil/bashсо следующим содержанием:
#!/bin/bashif[ $EUID -eq 0];then
echo "All your base are belong to us..."# We are root - do whatever you want to dofi/bin/bash "$@"
Давайте сделаем простой скрипт sample.sh:
#!/usr/bin/env bash
echo "Hello World"
Подтверждение концепции (в системе, где sudoхранится $PATH):
$ ./sample.sh
Hello World
$ sudo ./sample.sh
Hello World
$ export PATH="$HOME/.evil:$PATH"
$ ./sample.sh
Hello World
$ sudo ./sample.sh
All your base are belong to us...
Hello World
Обычно все классические оболочки должны быть расположены внутри, /binи если вы не хотите размещать их там по какой-либо причине, на самом деле не является проблемой разместить символическую ссылку, /binкоторая указывает на их реальное местоположение (или, возможно, /binсама является символической ссылкой), поэтому Я бы всегда пошел с #!/bin/shи #!/bin/bash. Слишком много всего сломалось бы, если бы они больше не работали. Дело не в том, что POSIX потребует эти позиции (POSIX не стандартизирует имена путей и, следовательно, он даже не стандартизирует функцию shebang), но они настолько распространены, что даже если система не предлагает /bin/sh, она, вероятно, все еще понимает #!/bin/shи знать, что с ним делать, и может ли это быть только для совместимости с существующим кодом.
Но для более современных, нестандартных, необязательных интерпретаторов, таких как Perl, PHP, Python или Ruby, на самом деле не указано, где они должны быть расположены. Они могут быть в, /usr/binно они могут также находиться в /usr/local/binили в совершенно другой ветви иерархии ( /opt/..., /Applications/...и т. Д.). Вот почему они часто используют #!/usr/bin/env xxxсинтаксис Шебанга.
Я нахожу это полезным, потому что, когда я не знал об env, до того, как начал писать скрипт, я делал это:
type nodejs > scriptname.js #or any other environment
а потом я модифицировал эту строку в файле в shebang.
Я делал это, потому что я не всегда помнил, где находится nodejs на моем компьютере - / usr / bin / или / bin /, поэтому для меня envэто очень полезно. Может быть, есть детали с этим, но это моя причина
Ответы:
Выполнение команды сквозной
/usr/bin/env
имеет преимущество ищет то , что по умолчанию версия программы находится в текущем окр ironment.Таким образом, вам не нужно искать его в определенном месте в системе, поскольку эти пути могут находиться в разных местах в разных системах. Пока он на вашем пути, он его найдет.
Одним из недостатков является то, что вы не сможете передать более одного аргумента (например, вы не сможете писать
/usr/bin/env awk -f
), если вы хотите поддерживать Linux, поскольку POSIX неопределен в отношении того, как должна интерпретироваться строка, и Linux интерпретирует все после первого пространство для обозначения одного аргумента. Вы можете использовать/usr/bin/env -S
в некоторых версиях,env
чтобы обойти это, но тогда сценарий станет еще менее переносимым и сломается на довольно недавних системах (например, даже Ubuntu 16.04, если не позже).Другим недостатком является то, что, поскольку вы не вызываете явный исполняемый файл, у него есть вероятность ошибок и проблем с безопасностью многопользовательских систем (например, если кому-то удалось получить вызываемый файл
bash
на вашем пути).В некоторых ситуациях первое может быть предпочтительным (например, запуск сценариев Python с несколькими версиями Python без необходимости переделки исполняемой строки). Но в ситуациях, когда безопасность находится в центре внимания, последнее предпочтительнее, так как оно ограничивает возможности внедрения кода.
источник
#!/usr/bin/env echo Hello
жалуется:/usr/bin/env: echo Hello: No such file or directory
. По-видимому, это рассматриваетсяecho Hello
как один аргумент/usr/bin/env
.env
команда, безусловно, позволяет передавать аргументы команде. Проблема заключается в семантике#!
строки, и это зависит от ядра. Последние ядра Linux допускают такие вещи, как#!/usr/bin/env command args
старые ядра Linux и другие системы.Использование
#!/usr/bin/env NAME
заставляет оболочку искать первое совпадение NAME в переменной окружения $ PATH. Это может быть полезно, если вы не знаете об абсолютном пути или не хотите его искать.источник
Вместо того, чтобы явно определять путь к интерпретатору, как
/usr/bin/bash/
при использовании команды env, интерпретатор ищется и запускается оттуда, где он был впервые найден. Это имеет как плюсы, так и минусыисточник
Если сценарии оболочки начинаются с
#!/bin/bash
, они всегда будут работать сbash
с/bin
. Если они однако начать с#!/usr/bin/env bash
, они будут искатьbash
в$PATH
и затем начать с первыми они могут найти.Почему это было бы полезно? Предположим, вы хотите запустить
bash
сценарии, для которых требуется bash 4.x или новее, но в вашей системе установлена толькоbash
3.x, и в настоящее время ваш дистрибутив не предлагает более новую версию, или вы не являетесь администратором и не можете изменить то, что установлено в этой системе. ,Конечно, вы можете скачать исходный код bash и создать свой собственный bash с нуля, разместив его,
~/bin
например. И вы также можете изменить свою$PATH
переменную в своем.bash_profile
файле, чтобы включить~/bin
в качестве первой записи (PATH=$HOME/bin:$PATH
поскольку~
не будет расширяться в$PATH
). Если вы сейчас позвонитеbash
, оболочка сначала будет искать его$PATH
по порядку, поэтому она начинается с того места~/bin
, где она найдет вашbash
. То же самое происходит, если скрипты ищут дляbash
использования#!/usr/bin/env bash
, поэтому эти скрипты теперь будут работать в вашей системе с использованием вашей пользовательскойbash
сборки.Недостатком является то, что это может привести к неожиданному поведению, например, один и тот же сценарий на одном и том же компьютере может работать с разными интерпретаторами для разных сред или пользователей с разными путями поиска, вызывая все виды головной боли.
Самым большим недостатком
env
является то, что некоторые системы допускают только один аргумент, поэтому вы не можете сделать это#!/usr/bin/env <interpreter> <arg>
, так как системы будут рассматривать<interpreter> <arg>
как один аргумент (они будут обрабатывать его, как если бы выражение было заключено в кавычки) и, таким образом,env
будут искать интерпретатор с именем<interpreter> <arg>
. Обратите внимание, что это не проблема самойenv
команды, которая всегда позволяла передавать несколько параметров, но с помощью анализатора shebang системы, которая анализирует эту строку еще до вызоваenv
. Между тем, это было исправлено в большинстве систем, но если ваш скрипт хочет быть сверхпортативным, вы не можете полагаться, что это было исправлено в системе, которую вы будете использовать.Он может даже иметь последствия для безопасности, например, если
sudo
он не был настроен для очистки окружающей среды или$PATH
был исключен из очистки. Позвольте мне продемонстрировать это:Обычно
/bin
это хорошо защищенное место, только тамroot
можно что-то изменить. Ваш домашний каталог, однако, не любая программа, которую вы запускаете, может внести в нее изменения. Это означает, что вредоносный код может поместить фальшивкуbash
в какой-то скрытый каталог, изменить его,.bash_profile
чтобы включить этот каталог в свой$PATH
, так что все используемые скрипты в#!/usr/bin/env bash
конечном итоге будут работать с этой фальшивкойbash
. Еслиsudo
держится$PATH
, у вас большие проблемы.Например, рассмотрим инструмент, создающий файл
~/.evil/bash
со следующим содержанием:Давайте сделаем простой скрипт
sample.sh
:Подтверждение концепции (в системе, где
sudo
хранится$PATH
):Обычно все классические оболочки должны быть расположены внутри,
/bin
и если вы не хотите размещать их там по какой-либо причине, на самом деле не является проблемой разместить символическую ссылку,/bin
которая указывает на их реальное местоположение (или, возможно,/bin
сама является символической ссылкой), поэтому Я бы всегда пошел с#!/bin/sh
и#!/bin/bash
. Слишком много всего сломалось бы, если бы они больше не работали. Дело не в том, что POSIX потребует эти позиции (POSIX не стандартизирует имена путей и, следовательно, он даже не стандартизирует функцию shebang), но они настолько распространены, что даже если система не предлагает/bin/sh
, она, вероятно, все еще понимает#!/bin/sh
и знать, что с ним делать, и может ли это быть только для совместимости с существующим кодом.Но для более современных, нестандартных, необязательных интерпретаторов, таких как Perl, PHP, Python или Ruby, на самом деле не указано, где они должны быть расположены. Они могут быть в,
/usr/bin
но они могут также находиться в/usr/local/bin
или в совершенно другой ветви иерархии (/opt/...
,/Applications/...
и т. Д.). Вот почему они часто используют#!/usr/bin/env xxx
синтаксис Шебанга.источник
Я нахожу это полезным, потому что, когда я не знал об env, до того, как начал писать скрипт, я делал это:
а потом я модифицировал эту строку в файле в shebang.
Я делал это, потому что я не всегда помнил, где находится nodejs на моем компьютере - / usr / bin / или / bin /, поэтому для меня
env
это очень полезно. Может быть, есть детали с этим, но это моя причинаисточник