Я искал различие между "." и "источник", встроенные команды и несколько источников (например, в этом обсуждении и странице справочника удара) предполагают, что это все равно.
Однако после проблемы с переменными среды, я провел тест. Я создал файл testenv.sh
это содержит:
#!/bin/bash
echo $MY_VAR
В командной строке я выполнил следующее:
> chmod +x testenv.sh
> MY_VAR=12345
> ./testenv.sh
> source testenv.sh
12345
> MY_VAR=12345 ./testenv.sh
12345
[обратите внимание, что 1-я форма возвратила пустую строку]
Так, этот небольшой эксперимент предполагает, что существует различие, в конце концов, где для "исходной" команды, дочерняя среда наследовала все переменные от родительской, где для "." этого не делает.
Я пропускаю что-то или, это - недокументированное / устаревшая функция удара?
[Удар GNU, версия 4.1.5 (1) - выпуск (x86_64-pc-linux-gnu)]
В Вашем вопросе вторая команда не использует ни одного .
окружите встроенный, ни source
встроенный. Вместо этого Вы на самом деле запускаете скрипт в отдельной оболочке, путем вызова его по имени как Вы был бы с любым другим исполняемым файлом. Это действительно дает ему отдельный набор переменных (хотя при экспорте переменной в ее родительской оболочке это будет переменной среды для любого дочернего процесса и поэтому будет включено в переменные дочерней оболочки). Если Вы изменяетесь /
к пространству затем это выполнило бы его с .
встроенный, который эквивалентен source
.
Это - синтаксис source
встроенная оболочка, который выполняет содержание сценария в текущей оболочке (и таким образом с переменными текущей оболочки):
source testenv.sh
Это - синтаксис .
встроенный, который действительно делает то же самое как source
:
. testenv.sh
Однако этот синтаксис запускает скрипт как исполняемый файл, запуская новую оболочку для выполнения его:
./testenv.sh
Это не использует .
встроенный. Скорее .
часть пути к файлу, который Вы выполняете. Вообще говоря, можно выполнить любой исполняемый файл в оболочке путем вызова его с именем, которое содержит по крайней мере один /
символ. Петлять в текущем каталоге, предшествуя ему ./
таким образом самый легкий путь. Если текущий каталог не находится в Вашем PATH
, Вы не можете запустить скрипт с командой testenv.sh
. Это должно предотвратить людей из случайно выполняющихся файлов в текущем каталоге, когда они намереваются выполнить системную команду или некоторый другой файл, который существует в некотором каталоге, перечисленном в PATH
переменная среды.
Начиная с петляния по имени (а не с source
или .
) выполнения это в новой оболочке, это будет иметь свой собственный набор переменных оболочки. Новая оболочка действительно наследовала переменные среды от обработки вызовов (который в этом случае является Вашей интерактивной оболочкой), и те переменные среды действительно становятся переменными оболочки в новой оболочке. Однако, чтобы переменная оболочки была передана новой оболочке, одно из следующего должно иметь место:
Переменная оболочки была экспортирована, заставив это быть переменной среды. Используйте export
оболочка, встроенная для этого. В Вашем примере можно использовать export MY_VAR=12345
чтобы установить и экспортировать переменную за один шаг, или если это уже установлено, можно просто использовать export MY_VAR
.
Переменная оболочки явно установлена и передана для команды, которую Вы выполняете, вызывая ее быть переменной среды на время выполняемой команды. Это обычно выполняет это:
MY_VAR=12345 ./testenv.sh
Если MY_VAR
переменная оболочки, которая не была экспортирована, можно даже работать testenv.sh
с MY_VAR
переданный как переменная среды путем установки его на себя:
MY_VAR="$MY_VAR" ./testenv.sh
./
Синтаксис для сценариев требует, чтобы строка Hashbang работала (правильно)Между прочим, обратите внимание на то, что, когда Вы вызываете исполняемый файл по имени как выше (а не с .
или source
окружите созданный-ins), что программная оболочка используется для выполнения, она обычно не определяется, какой оболочкой Вы выполняете ее от. Вместо этого:
Для двоичных файлов ядро может быть настроено для петляния того конкретного типа. Это исследует первые два байта файла для "магического числа", которое указывает, какой двоичный исполняемый файл это. Это - то, как исполняемые двоичные файлы могут работать.
Это, конечно, чрезвычайно важно, потому что сценарий не может работать без оболочки или другого интерпретатора, который является исполняемым двоичным файлом! Плюс, много команд и приложений являются скомпилированными двоичными файлами, а не сценариями.
(#!
текстовое представление "магического числа", указывающего на текстовый исполняемый файл.)
Для файлов, которые, как предполагается, работают в оболочке или другом интерпретируемом языке, первая строка похожа:
#!/bin/sh
/bin/sh
может быть заменен тем, что другая оболочка или интерпретатор предназначается для запущения программы. Например, программа Python могла бы запуститься со строки:
#!/usr/bin/python
Эти строки называют hashbang, хижиной и многими другими аналогичными именами. Посмотрите эту запись FOLDOC, эту статью Wikipedia, и #!/bin/sh считанный интерпретатором? для получения дополнительной информации.
Если текстовый файл отмечен исполняемый файл, и Вы выполняете его от своей оболочки (как ./filename
) но это не начинается #!
, ядру не удается выполнить его. Однако видя, что это произошло, Ваша оболочка попытается выполнить его путем передачи ее имени к некоторой оболочке. Существует немного требований, помещенных в то, какая оболочка, которая является ("оболочка выполню команду, эквивалентную вызову оболочки..."). На практике, некоторые оболочки - включая bash
* - выполните другой экземпляр себя, в то время как другие используют /bin/sh
. Я настоятельно рекомендую, чтобы Вы избежали этого и использовали hashbang строку вместо этого (или запустили скрипт путем передачи его желаемому интерпретатору, например, bash filename
).
*руководство Bash GNU, 3.7.2 Поисков Команды и Выполнение: "Если это выполнение перестало работать, потому что файл не находится в формате исполняемых файлов, и файл не является каталогом, это, как предполагается, сценарий оболочки, и оболочка выполняет его, как описано в Сценариях оболочки".
Да, Вы пропускаете что-то.
я думаю, что Вы путаете '.', который означает текущий каталог, как в ./testenv.sh
и '.', который означает source
(который является встроенной командой). Таким образом в случае, когда'.' средства source
это было бы . ./testenv.sh
. Иметь смысл?
Так пробуют это:
MY_VAR=12345
. ./testenv.sh