Unix:源和导出有什么区别?

时间:2013-03-18 10:32:09

标签: linux unix

我正在编写一个shell脚本,用于读取具有key = value对的文件,并将这些变量设置为环境变量。但我有一个疑问,如果我做source file.txt会将该文件中定义的变量设置为环境变量,或者我应该逐行读取文件并使用export命令设置它?

在这种情况下,源命令是否与导出不同?

2 个答案:

答案 0 :(得分:16)

当你source文件时,除非设置了allexport选项,否则分配将被设置为变量而不是环境变量。如果您希望将变量放在环境中,则使用allexportsource文件比读取文件和显式使用export要简单得多。换句话说,你应该这样做:

set -a
. file.txt

(我更喜欢.因为它比source更便携,但sourcebash中运行得很好。)

答案 1 :(得分:2)

source.)与export(以及文件锁[flock]末尾的内容):

简而言之:

  1. source some_script.sh或与POSIX兼容的等效语言. some_script.sh从其他脚本中引入中的变量,而
  2. export my_var="something" 将变量推送到其他脚本/进程,这些脚本/进程将从当前脚本/进程中调用/开始。

在Linux Shell脚本中使用source some_script.sh. some_script.sh就像在Python中使用import some_module或在C或C ++中使用#include <some_header_file.h>它从源脚本中引入变量。

使用export some_var="something"有点像在本地设置该变量,因此它可用于当前脚本或进程的其余部分,然后将其传递给任何子项和所有子项-您可能会在此之后调用的脚本或进程。

更多详细信息:

所以,这个:

# export `some_var` so that it is set and available in the current script/process,
# as well as in all sub-scripts or processes which are called from the
# current script/process
export some_var="something"
# call other scripts/processes, passing in `some_var` to them automatically
# since it was just exported above! 
script1.sh  # this script now gets direct access to `some_var`
script2.sh  # as does this one
script3.sh  # and this one

就像一样,您已经这样做了:

# set this variable for the current script/process only
some_var="something" 
# call other scripts/processes, passing in `some_var` to them **manually**
# so they can use it too 
some_var="something" script1.sh  # manually pass in `some_var` to this script
some_var="something" script2.sh  # manually pass in `some_var` to this script
some_var="something" script3.sh  # manually pass in `some_var` to this script

除了上面的第一个版本(我们称为export some_var="something"实际上具有将变量递归传递或导出到子流程)之外,因此如果我们从当前脚本/进程内部调用script1.sh,则script1.sh将从当前脚本中获取导出的变量,并且如果script1.sh调用script5.sh,而script5.sh调用script10.sh,那么这两个脚本也会自动获取导出的变量。这与上述手动案例形成对比,在手动案例中,只有那些在调用脚本时使用手动设置的变量显式调用的脚本才能获取它们,因此子脚本不会从其调用脚本中自动获取任何变量!

如何“取消导出”变量:

请注意,导出变量后,在其上调用unset将“取消导出”,如下所示:

# set and export `some_var` so that sub-processes will receive it
export some_var="something"
script1.sh  # this script automatically receives `some_var`

# unset and un-export `some_var` so that sub-processes will no longer receive it
unset some_var
script1.sh  # this script does NOT automatically receive `some_var`

总结:

  1. source. 导入
  2. export 导出
  3. unset 取消导出

示例:

创建此脚本:

source_and_export.sh

#!/bin/bash

echo "var1 = $var1"
var2="world"

然后将其标记为可执行文件:

chmod +x source_and_export.sh

现在这是我在终端上运行一些命令以使用此脚本测试source.)和export命令的过程。键入您在以$开头的行之后看到的命令(不包括注释)。其他行是输出。依次运行命令,一次运行一个命令:

$ echo "$var1"              # var1 contains nothing locally

$ var1="hello"              # set var1 to something in the current process only
$ ./source_and_export.sh    # call a sub-process
var1 =                      # the sub-process can't see what I just set var1 to
$ export var1               # **export** var1 so sub-processes will receive it
$ ./source_and_export.sh    # call a sub-process
var1 = hello                # now the sub-process sees what I previously set var1 to
$ echo "$var1 $var2"        # but I can't see var2 from the subprocess/subscript
hello 
$ . ./source_and_export.sh  # **source** the sub-script to _import_ its var2 into the current process
var1 = hello
$ echo "$var1 $var2"        # now I CAN see what the subprocess set var2 to because I **sourced it!**
hello world                 # BOTH var1 from the current process and var2 from the sub-process print in the current process!
$ unset var1                # unexport (`unset`) var1
$ echo "$var1"              # var1 is now NOT set in the current process
$ ./source_and_export.sh    # and the sub-process doesn't receive it either
var1 = 
$ var1="hey"                # set var1 again in the current process
$ . ./source_and_export.sh  # if I **source** the script, it runs in the current process, so it CAN see var1 from the current process!
var1 = hey                  # notice it prints
$ ./source_and_export.sh    # but if I run the script as a sub-process, it can NOT see var1 now because it was `unset` (unexported)
var1 =                      #   above and has NOT been `export`ed again since then!
$

将文件用作全局变量

有时候,在编写脚本以启动程序等时,我遇到了export似乎工作不正常的情况。在这种情况下,有时人们必须求助于使用文件本身作为全局变量,将信息从一个程序传递到另一个程序。这是可以做到的。在此示例中,文件“〜/ temp / .do_something”的存在用作进程间布尔变量:

# In program A, if the file "~/temp/.do_something" does NOT exist, 
# then create it
mkdir -p ~/temp
if [ ! -f ~/temp/.do_something ]; then
    touch ~/temp/.do_something  # create the file
fi


# In program B, check to see if the file exists, and act accordingly

mkdir -p ~/temp
DO_SOMETHING="false"
if [ -f ~/temp/.do_something ]; then
    DO_SOMETHING="true"
fi

if [ "$DO_SOMETHING" == "true" ] && [ "$SOME_OTHER_VAR" == "whatever" ]; then 
    # remove this global file "variable" so we don't act on it again
    # until "program A" is called again and re-creates the file
    rm ~/temp/.do_something 
    do_something
else
    do_something_else
fi

如上所述,仅检查文件的存在性对于在程序和进程之间全局传递布尔条件非常有用。但是,如果您需要传递更复杂的变量(例如字符串或数字),则可能需要通过将这些值写入文件来实现。在这种情况下,应使用文件锁定函数flock,以确保进程间同步。它是一种过程安全(即“进程间”)互斥体原语。您可以在这里阅读有关内容:

  1. shell脚本flock命令:https://man7.org/linux/man-pages/man1/flock.1.html。另请参见man flockman 1 flock
  2. Linux库C命令:https://man7.org/linux/man-pages/man2/flock.2.html。另请参见man 2 flock。您必须在C文件中#include <sys/file.h>才能使用此功能。

参考:

  1. https://askubuntu.com/questions/862236/source-vs-export-vs-export-ld-library-path/862256#862256
  2. 我自己的实验和测试
  3. 我将上面的示例添加到我在GitHub上的项目中的bash文件夹下:https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world