Будет ли какая-то разница или это просто личный выбор?
Какая разница в использовании #!/Usr/bin/env или #!/Bin/env в shebang?
Ответ 1
#!<interpreter> <arguments>
пытается запустить <interpreter> <arguments>
, чтобы прочитать и запустить остальную часть файла.
Итак, #!/usr/bin/env
означает, что должна быть программа с именем /usr/bin/env
;
#!/bin/env
означает, что должна быть программа под названием /bin/env
.
В некоторых системах есть один, а не другой.
По моему опыту, большинство из них имеют /usr/bin/env
, поэтому #!/usr/bin/env
чаще встречается.
Unix-системы попытаются запустить <interpreter>
с помощью execve
, поэтому он должен быть полным путем, а #!env
без пути не будет работать.
Ответ 2
Объяснение Микеля велико, оно пропускает только небольшой факт (что весьма важно), он пропускает только один аргумент, включая все пробелы:
#!<Interpreter> <argument>
Результаты при вызове:
$ <Interpreter> '<argument>' path_to_calling_script
Итак, для примера:
$ cat /tmp/test
#!/usr/bin/env python
print "hi"
$ /tmp/test
совпадает с вызовом:
$ /usr/bin/env "python" /tmp/test
Кавычки пытаются показать, что если вы добавите какой-либо флаг или другие значения, это будет часть вызываемого аргумента.
#!/bin/bash -c /bin/env python
Будет интерпретироваться как:
$ /bin/bash "-c /bin/env python"
Что не будет работать.
Ответ 3
/usr/bin/env
является мягкой ссылкой на /bin/env
. По существу, вы используете /bin/env
Ответ 4
Исторически в UNIX было 2 набора двоичных файлов:
-
/
Файловая система смонтирована в начале загрузки. - Возможно,
/usr
был смонтирован позже, возможно, запустив сценарии и программы из/
для организации монтирования. Пример: некоторые сайты сэкономили место, подключив /usr из сети, но сначала вам нужно войти в сеть. Пример: это большая локальная файловая система, но если она повреждена, вы хотите, чтобы такие инструменты, какfsck
попытались ее исправить.
Таким образом, /bin
и /sbin
(используя /lib
) должны были содержать минимальную систему, включающую по крайней мере оболочку в /bin/sh, основы сценариев, такие как /bin/echo
, /bin/test
и т.д., Системные инструменты, такие как /bin/mount
или /sbin/mount
и /bin/fsck
...
Таким образом, в разных Unix-системах практически любая программа могла быть:
- в /usr/bin/но НЕ /bin
- в /bin, но НЕ /usr/bin
- в обоих, так же, как символическая ссылка
- в обоих но разные! Например, в некоторых системах игра
/bin/sh
является очень минимальной оболочкой (например,dash
) для более быстрого запуска, но символическая ссылка/usr/bin/sh
→/usr/bin/bash
(iirc, вызывая bash как "sh", помещает его в какой-то режим posix, но это все же другая более мощная оболочка).
Таким образом, хитрость использования env
для написания переносимых скриптов - env
просто делает поиск в PATH. (Это также полезно в других местах, которые не выполняют поиск PATH, например, docker exec
.)
Что изменилось
Это были действительные случаи использования, но современный Linux последовал подобный аргументу "нужен небольшой UserSpace для монтирования/восстановления основного UserSpace" для /
себя тоже! Были введены сводный системный вызов и initrd
, и выросли инструменты для копирования в него нужных вам частей.
/usr унификация
Теперь /
vs /usr
возможно, утратил свою цель. И то, и другое на одной файловой системе и символических ссылках было выполнимо для всех в принципе, хотя некоторые конкретные установки сломались бы и должны были измениться...
См. Https://lwn.net/Articles/483921/ с 2012 года для обзора этой идеи "/usr unification". Например, Fedora завершила это: https://fedoraproject.org/wiki/Features/UsrMove. Многие другие дистрибутивы не имеют или все еще обсуждают его, или сглаживают некоторые виды, чтобы сломать меньше пользователей. Например, смотрите подготовку к Debian: https://wiki.debian.org/UsrMerge.