来源和出口有什么区别?

2024-10-25 08:42:00
admin
原创
238
摘要:问题描述:我正在编写一个 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__'

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2599  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1556  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   38  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   32  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   28  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用