В чем разница между "source x", ". X" и "./x" в Bash?
У меня есть один источник bash run.sh
следующее,
#!/bin/bash
if [ $# -ne 1 ]; then
exit
fi
...
когда я выполняю это двумя способами, это ведет себя по-разному. Первый способ
source run.sh
Он закроет терминал после выполнения. Второй способ
./run.sh
это просто завершит выполнение скрипта и останется на терминале. Я спрашиваю, есть ли команда для выхода из скриптов bash для обоих source run.sh
а также ./run.sh
выполнение. я пытался return
тоже, который не очень хорошо работает под ./run.sh
выполнение.
В целом меня интересует, почему это происходит, и в чем разница между использованием "источника" и "". для выполнения скрипта?
3 ответа
Прежде чем ответить, я думаю, что некоторые разъяснения необходимы. Давайте проанализируем следующие три строки:
source run.sh
. run.sh
./run.sh
Первые две строки абсолютно идентичны: .
на самом деле псевдоним для source
, Какие source
действительно выполняет сценарий оболочки в текущем контексте, следовательно, вызов exit
выйдет из оболочки.
Третья строка (которая вас смущает) не имеет ничего общего с другими. ./run.sh
это просто путь, и такой же, как (например) /home/user/run.sh
или же /usr/bin/something
, Всегда помните, что команды в оболочке разделяются пробелом. Таким образом, в этом случае команда не .
, но это ./run.sh
это означает, что субоболочка будет выполнена и что exit
будет иметь эффект только для суб-оболочки.
Три способа:
Вы можете заключить скрипт в функцию и использовать только return.
#!/usr/bin/env bash
main() {
...
return 1
...
}
main "$@"
Вы можете проверить, является ли сценарий источником интерактивной оболочки.
if [[ $- = *i* ]]; then
return 1
else
exit 1
fi
Вы можете попытаться вернуться, и, если это не удастся, выйти.
return 1 2>/dev/null || exit 1
Думайте о команде "источник" как в операторе "включить". Он берет содержимое аргумента и запускает его так, как если бы он был запущен напрямую. В этом случае ваша команда 'source' с аргументом 'run.sh', а run.sh выполняется точно так же, как если бы вы ввели содержимое run.sh в вашу командную строку.
Когда вы запускаете "./run.sh", "./run.sh" является вашей командой и не имеет аргументов. Поскольку этот файл является обычным текстом, а не двоичным, ваша оболочка ищет интерпретатор в shebang ('#!' В первой строке) и находит '/bin/bash'. Таким образом, ваша оболочка затем запускает новый экземпляр bash, и содержимое run.sh запускается внутри этого нового экземпляра.
В первом случае, когда bash достигает команды exit, она выполняется точно так, как если бы вы ввели ее в командную строку. Во втором случае это выполняется в процессе bash, который запустила ваша оболочка, поэтому только этот экземпляр bash получает команду 'exit'.
Когда вы вводите строку в bash, все, что находится перед первым пробелом, обрабатывается как команда, а все последующее - как аргументы. Команда '.' является псевдонимом "источник". Когда ты бежишь ". run.sh 'the'. ' это отдельная команда, так как она отделена от аргументов пробелом. Когда вы запускаете "./run.sh", ваша команда - "./run.sh" и "." является частью относительного пути к run.sh с символом "." представляющий вашу текущую папку.