来源和出口有什么区别?

2024-10-25 08:42:00
admin
原创
68
摘要:问题描述:我正在编写一个 shell 脚本,用于读取具有 key=value 对的文件并将这些变量设置为环境变量。但我有一个疑问,如果我这样做,source file.txt是否会将该文件中定义的变量设置为环境变量,或者我应该逐行读取文件并使用 export 命令进行设置?在这种情况下,源命令与导出命令不同吗...

问题描述:

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

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


解决方案 1:

当您打开source文件时,将设置赋值,但不会导出变量,除非allexport已设置选项。如果您希望导出所有变量,则使用文件比读取文件并明确使用allexport要简单得多。换句话说,您应该这样做:source`export`

set -a
. file.txt

(我更喜欢,.因为它比 更便携source,但source在 中运行良好bash。)

请注意,导出变量并不会使其成为环境变量。它只是使其成为任何子 shell 中的环境变量。

解决方案 2:

source( .) vs 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有点像import some_module在 Python、#include <some_header_file.h>C 或 C++ 中使用。它从正在使用的脚本中引入变量。

使用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 取消出口

例子

创建此脚本:

源和导出.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 (my terminal) 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) above and has NOT been `export`ed 
                            # again since then!
var1 =                      # So, var1 is not exported to the subprocess.
$

使用文件作为进程之间的全局变量

有时,在编写脚本来启动程序等时,我遇到了一些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。您必须#include <sys/file.h>在 C 文件中使用此函数。

参考

  1. 询问 Ubuntu:source 与 export 与 export LD_LIBRARY_PATH

  2. 我自己的实验和测试。

  3. 我将把上述示例添加到我在 GitHub 上的项目中,bash文件夹为:https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world

参见

  1. 我的个人网站文章“如何在 Bash 中编写、导入、使用和测试库?”

这更多地讨论了如何使用操作员来获取文件,以及如何通过使用这种类似 Python 的魔法使.文件在获取文件时不运行:

if [ "$__name__" = "__main__" ]; then
    main "$@"
fi
  1. 我对从 shell 脚本导入函数的回答

  2. 我对Bash 与 Python 的等效项是什么的回答if __name__ == '__main__'

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用