Ответы:
Для вашего конкретного сценария будет работать любой из этих способов, за исключением того, что ./script.sh
требуется выполнение и читаемые биты, а bash script.sh
требуется только читаемый бит.
Причина разницы в требованиях к разрешениям заключается в том, как загружается программа, которая интерпретирует ваш скрипт:
./script.sh
заставляет вашу оболочку запускать файл, как если бы он был обычным исполняемым файлом.Оболочка разветвляется и использует системный вызов (например execve
), чтобы заставить операционную систему выполнить файл в разветвленном процессе. Операционная система проверит права доступа к файлу (следовательно, необходимо установить бит выполнения) и направит запрос загрузчику программы , который просматривает файл и определяет, как его выполнить. В Linux скомпилированные исполняемые файлы начинаются с магического числа ELF , а сценарии начинаются с #!
( hashbang ). Заголовок hashbang означает, что файл является сценарием и должен интерпретироваться программой, указанной после hashbang. Это позволяет самому сценарию сообщать системе, как интерпретировать сценарий.
С вашим скриптом загрузчик программы будет выполнен /bin/bash
и передан ./script.sh
в качестве аргумента командной строки.
bash script.sh
заставляет вашу оболочку работать bash
и передавать script.sh
в качестве аргумента командной строкиТаким образом, операционная система будет загружаться bash
(даже не смотря на это script.sh
, потому что это просто аргумент командной строки). Созданный bash
процесс будет интерпретировать, script.sh
потому что он передается в качестве аргумента командной строки. Поскольку script.sh
считывается только bash
как обычный файл, бит выполнения не требуется.
Я рекомендую использовать ./script.sh
хотя, потому что вы можете не знать, какой интерпретатор требует сценарий. Так что пусть загрузчик программы определит это для вас.
. ./script.sh
- это не то же самое, что bash script.sh
(или ./script.sh
. Рассмотрим скрипт #!/usr/bin/python -V
<newline> print test
.
. script.sh
. Но я согласен с людьми, которые не одобряют использование .
команды в сценариях, которые не должны вызываться таким образом. Я удивлен тем, что никто не упомянул, что, если скрипт содержит exit
команды и вы их набираете, он может выйти из системы. Менее страшная проблема будет, если скрипт выполнит cd
, поскольку это также повлияет на родительскую (интерактивную) оболочку.
bash script.sh
вызывает скрипт напрямую с помощью bash.
./script.sh
использует Шебанг, #!/bin/bash
чтобы определить, как выполнить.
Если вы действительно хотите знать, какой двоичный файл выполняется, если вы сделаете a, bash script.sh
вы можете узнать с помощью which bash
.
Так что в вашем примере это не имеет значения. Да, вы должны chmod +x script.sh
иметь возможность выполнить его напрямую через ./script.sh
.
/bin/bash
это первый bash
в вашем $PATH
.
#!/bin/bash
работает, только если есть/bin/bash
./script.sh
.
Создайте файл Delete_Self.sh примерно так:
#!/bin/rm
echo I am still here!
Запустите этот скрипт, как sh Delete_Self.sh
вы увидите "Я все еще здесь!" повторил в ответ.
Сделайте его исполняемым и запустите его, так как ./Delete_Self.sh
вы увидите, что ничего не отражено, а сам файл Delete_Self.sh
исчез.
Так что разница в том, что:
bash script.sh
будет игнорировать #! строка, потому что bash указан как программа для запуска script.sh../script.sh
будет читать #! строка для определения программы для запуска script.sh
.В дополнение к другим ответам полезно знать разницу между запуском скрипта через ./script.sh
(i) и source ./script.sh
(ii) - версия (i) создает новую оболочку для запуска команды, тогда как (ii) запускает ее в текущая оболочка - которая может быть обязательной, если исполняемый файл изменяет переменные среды, которые необходимо сохранить после выхода из исполняемого файла. Например, чтобы активировать среду Python Conda, необходимо использовать следующее:
source activate my_env
NB. Другой альтернативой, с source
которой вы можете столкнуться, является .
встроенная функция, т.е.
. activate my_env