Відповіді:
Для вашого конкретного сценарію будь-який спосіб буде працювати, за винятком того, що ./script.sh
вимагає виконання та читання бітів, тоді bash script.sh
як потрібен лише біт для читання.
Причина різниці вимог дозволів полягає в тому, як завантажується програма, що інтерпретує ваш сценарій:
./script.sh
змушує вашу оболонку запустити файл так, ніби це був звичайний виконуваний файл.Оболонка розкручується і використовує системний виклик (наприклад execve
), щоб змусити операційну систему виконувати файл у роздвоєному процесі. Операційна система перевірить права доступу до файлу (отже, слід встановити біт виконання) та передасть запит на завантажувач програми , який розглядає файл та визначає спосіб його виконання. У Linux компільовані виконувані файли починаються з магічного числа ELF , а сценарії починаються з #!
( хешбанг ). Заголовок хешбангу означає, що файл є скриптом і його слід інтерпретувати програмою, яка вказана після хешбангу. Це дозволяє самому сценарію розповісти системі, як інтерпретувати сценарій.
З вашим сценарієм завантажувач програми виконає /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
команди, і ви його джерелом, він може вийти з системи. Менш гострою проблемою буде, якщо сценарій робить a cd
, оскільки це також вплине на батьківську (інтерактивну) оболонку.
bash script.sh
викликає сценарій безпосередньо за допомогою bash.
./script.sh
використовує шебанг #!/bin/bash
для визначення способу виконання.
Якщо ви дійсно хочете знати, який двійковий файл виконується, якщо ви це робите, 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) та джерелом ./script.sh
(ii) - версія (i) створює нову оболонку, в якій можна запустити команду, тоді як (ii) запускає її в поточна оболонка - що може бути обов'язковим, якщо виконуваний файл змінює змінні середовища, які потрібно зберегти після завершення виконання файлу. Наприклад, для активації середовища python conda необхідно використовувати наступне:
source activate my_env
NB Ще одна альтернатива тому, source
що ви можете зіткнутися, - це .
вбудований, тобто
. activate my_env