В чем разница между «источником x», «. x "и" ./x "в Bash?

10

У меня есть один источник 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 .

В целом, меня интересует, почему это происходит, и какая разница между использованием «источника» и «.». для выполнения скрипта?

    
задан Richard 26.02.2012 в 17:11
источник

3 ответа

16

Прежде чем ответить, я думаю, что необходимы некоторые разъяснения. Давайте проанализируем следующие три строки:

source run.sh
. run.sh
./run.sh

Первые две строки точно идентичны: . на самом деле является псевдонимом для source . Какой source выполняет скрипт оболочки в текущем контексте, поэтому вызов exit выйдет из оболочки.

Третья строка (та, которая вас смущает) не имеет ничего общего с другими строками. ./run.sh - это всего лишь путь и совпадает с (например) /home/user/run.sh или /usr/bin/something . Всегда помните, что команды в оболочке разделены пробелом. Таким образом, в этом случае команда не является . , но является ./run.sh : это означает, что будет выполняться под-оболочка и что exit будет иметь эффект только для под-оболочки.

    
ответ дан Andrea Corbellini 26.02.2012 в 17:39
источник
4

Три способа:

Вы можете заключить скрипт в функцию и использовать только return.

#!/usr/bin/env bash
main() {
    ...
    return 1
    ...
}
main "[email protected]"

Вы можете проверить, работает ли сценарий с помощью интерактивной оболочки.

if [[ $- = *i* ]]; then
    return 1
else
    exit 1
fi

Вы можете попытаться вернуться, и если это не удастся, выйдите.

return 1 2>/dev/null || exit 1
    
ответ дан geirha 26.02.2012 в 19:00
1

Подумайте о команде «источник», как в заявлении «include». Он принимает содержание аргумента и запускает его так, как если бы он запускался напрямую. В этом случае ваша команда является «источником» с аргументом «run.sh», а run.sh выполняется точно так же, как если бы вы ввели содержимое run.sh в свою командную строку.

Когда вы запускаете './run.sh', './run.sh' - ваша команда, и у нее нет аргументов. Поскольку этот файл является текстовым, а не бинарным, ваша оболочка ищет интерпретатора в shebang ('#!' В первой строке) и находит '/ bin / bash'. Таким образом, ваша оболочка запускает новый экземпляр bash, и содержимое run.sh запускается внутри этого нового экземпляра.

В первом случае, когда bash достигает команды «exit», она выполняется точно так же, как если бы вы ввели ее в командную строку. Во втором случае он выполняется в процессе bash, в котором запущена ваша оболочка, поэтому только этот экземпляр bash получает команду «exit».

Когда вы вводите строку в bash, все, что перед первым пространством рассматривается как команда, и все, что следует за ними, рассматриваются как аргументы. Команда '.' является псевдонимом «источника». Когда вы запустите ». run.sh ''. ' является собственной командой, поскольку она отделена от аргументов пробелом. Когда вы запускаете «./run.sh», ваша команда «./run.sh» и «.» является частью относительного пути к run.sh с '.' представляя вашу текущую папку.

    
ответ дан smokes2345 07.04.2015 в 17:18