Nano Hash - криптовалюты, майнинг, программирование

В чем разница между #! / Usr / bin / env bash и #! / Usr / bin / bash?

В чем разница между этими двумя операторами в заголовке сценария Bash:

  1. #!/usr/bin/env bash

  2. #!/usr/bin/bash

Когда я проконсультировался с env справочной страницей, я получил следующее определение:

 env - run a program in a modified environment

Что это значит?

03.05.2013

  • См. этот вопрос и мой ответ. 03.05.2013
  • Кто мне скажет, почему этот вопрос закрыт, не связан с программированием или разработкой ПО? 03.05.2013
  • Я согласен, что это не не по теме, но, вероятно, это дубликат нескольких других вопросов, таких как этот. 03.05.2013
  • Этот вопрос не должен был быть помечен как не по теме. Ему просто нужно 5 человек с рейтингом выше 3000, чтобы отметить его как тематический, и его можно будет открыть повторно. Это вопрос - конкретно о программировании. 03.02.2014
  • @DanijelJ: Я согласен, что это не не по теме, но это дубликат. Мы могли проголосовать за повторное открытие, а затем проголосовать за его закрытие как дубликат. Вряд ли это стоит усилий. 30.05.2014
  • По теме: Почему #! / Usr / bin / env bash превосходит #! / Bin / bash? на SO 29.09.2015
  • Я в шоке. Шокирован, обнаружив, что документация по Linux изобилует тавтологиями. xkcd.com/703 git-man-page-generator.lokaltog.net 30.10.2015
  • Одно из основных различий заключается в том, что в зависимости от системы #!/usr/bin/bash не будет работать. В моей системе (Ubuntu 17.04) bash равно /bin/bash, а /usr/bin/bash нет. Различие между /bin и /usr/bin в значительной степени условно. И чтобы добавить к легкомыслию, большинство систем помещают команду env в /usr/bin, но это не гарантируется. 13.11.2017
  • затем создайте символическую ссылку. Но это определенно БЫЛО по теме. 10.12.2020

Ответы:


1

Выполнение команды через /usr/bin/env дает преимущество поиска той версии программы, которая используется по умолчанию в вашем текущем окружении.

Таким образом, вам не нужно искать его в определенном месте в системе, поскольку эти пути могут находиться в разных местах в разных системах. Пока он на вашем пути, он его найдет.

Одним из недостатков является то, что вы не сможете передать более одного аргумента (например, вы не сможете написать /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 без необходимости переделывать исполняемую строку). Но в ситуациях, когда в центре внимания безопасность, предпочтительнее второе, поскольку оно ограничивает возможности внедрения кода.

03.05.2013
  • Другой недостаток заключается в том, что вы не можете передать интерпретатору дополнительный аргумент. 03.05.2013
  • @KeithThompson: Неверная информация .. Вы можете передать параметры базовому интерпретатору, используя / usr / bin / env! 30.05.2014
  • @GauravAgarwal: Нет в моей системе. Скрипт, содержащий только одну строку: #!/usr/bin/env echo Hello жалуется: /usr/bin/env: echo Hello: No such file or directory. Очевидно, он рассматривает echo Hello как единственный аргумент для /usr/bin/env. 30.05.2014
  • @KeithThompson: Не могли бы вы предоставить больше информации о вашей системе? 06.06.2014
  • @KeithThompson, версия env для GNU Coreutils позволяет передавать аргументы команде. Env FreeBSD также , похоже, поддерживает его. Что ты используешь? :) 18.12.2014
  • @ AndréLaszlo: Команда env, безусловно, позволяет передавать аргументы команде. Проблема заключается в семантике строки #!, которая зависит от ядра. Последние ядра Linux допускают такие вещи, как #!/usr/bin/env command args, но более старые ядра Linux и другие системы - нет. 18.12.2014
  • Да, я только что проверил. Извините, мне следовало более внимательно прочитать ваш комментарий :) stackoverflow.com/questions/3306518/ 18.12.2014
  • Почему в блоке кода есть обратные кавычки? Разве их нельзя удалить? 31.07.2017
  • Сделали команду более заметной? Честно говоря, это было четыре года назад, так что у меня нет законного оправдания. В сценарии оболочки вы правы, их бы там не было, и, надо признать, я тогда не так сильно углублялся в разметку SE. 01.08.2017
  • Примечание: предполагается, что env должен находиться в / usr / bin / env в большинстве систем. Во многих из них bash находится в / bin / bash, поэтому использование / usr / bin / env может быть небольшой гибкостью ... другое примечание: в некоторых (старых?) Системах / usr - это другой раздел, который может быть не смонтирован, и, возможно, по этой причине обычно используется #! / bin / bash, а не #! / usr / bin / bash 29.06.2018

  • 2

    Использование #!/usr/bin/env NAME заставляет оболочку искать первое совпадение NAME в переменной окружения $ PATH. Это может быть полезно, если вы не знаете абсолютный путь или не хотите его искать.

    03.05.2013
  • По крайней мере, вы должны знать, где находится env :). 22.03.2016
  • Отличный ответ. Кратко объясняет, что делает env shebang, а не говорит, что выбирает программу на основе конфигурации вашей системы. 16.11.2018

  • 3

    Если сценарии оболочки начинаются с #!/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 со следующим содержанием:

    #!/bin/bash
    
    if [ $EUID -eq 0 ]; then
      echo "All your base are belong to us..."
      # We are root - do whatever you want to do
    fi
    
    /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 shebang.

    30.04.2019

    4

    Вместо явного определения пути к интерпретатору, как в /usr/bin/bash/, с помощью команды env, интерпретатор ищется и запускается оттуда, где он был впервые найден. У этого есть плюсы и минусы

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

  • 5

    Я считаю это полезным, потому что, когда я не знал о env, до того, как я начал писать скрипт, я делал это:

    type nodejs > scriptname.js #or any other environment
    

    а затем я изменил эту строку в файле на shebang.
    Я делал это, потому что я не всегда помнил, где находится nodejs на моем компьютере - / usr / bin / или / bin /, поэтому для меня env очень полезно. Может быть, с этим есть подробности, но это моя причина

    14.08.2017
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..