Shell和环境变量之间的区别

40
什么是shell变量和环境变量?它们有什么区别?这些变量存储在哪里?
5个回答

33

引用此来源

标准UNIX变量分为两类,环境变量和shell变量。广义上讲,shell变量仅适用于当前shell实例,并用于设置短期工作条件;环境变量具有更广泛的意义,在登录时设置的变量在会话期间有效。按照惯例,环境变量使用大写字母,而shell变量使用小写字母。

要列出所有环境变量,请使用printenv命令,要列出所有shell变量,请使用set命令。

您会注意到环境变量存储更长期的值,例如:

HOME=/home/adam

这个值相对稳定,很少改变,而shell变量存储本地、临时的、特定于shell的值,例如:

PWD=/tmp

每次更改当前目录时都会更改它。

对于大多数实际任务,通过在您的~/.bashrc文件中添加export VARIABLE_NAME=VALUE来设置环境变量值。


环境变量是用户定义的吗?而 shell 变量是系统定义的吗?另外,您提到的是命令,而不是变量所在的位置? - sunil
“变量所在的位置”是什么意思?指的是你在哪里设置它们的值,还是指(技术上)存储在计算机内存中的位置? - Adam Matan
是否有任何文件存储它们?它们是用户定义的还是预定义的? - sunil
2
你引用了“按照惯例,环境变量使用大写字母,而shell变量使用小写字母命名。”,但你向我们展示了大小写字母都用于shell和环境变量。 - zell
4
为了提供更符合规范的来源,请参阅 POSIX 规范中的“环境变量”部分,网址为 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html。大写字母用于可以修改 shell 和 POSIX 指定工具行为的变量(无论是导出还是其他方式);而小写字母应该用于应用程序定义的变量,包括环境变量,这些变量不应该被认为会修改 POSIX 指定工具行为。 - Charles Duffy
显示剩余2条评论

19

对于Bash shell:

Shell变量与环境变量在不同方面有所不同:

♦ Shell变量仅适用于当前shell,并不会被子进程继承。例如,假设您从shell运行另一个应用程序,则该应用程序将不会继承shell变量:

$ SHELL_VAR=xyz
$ firefox

SHELL_VAR将不会在子进程(firefox)的环境中可用。

♦ 相反,父进程(这里是shell)的环境变量将被所有子进程继承:

$ export SHELL_VAR=xyz
$ firefox

♦ Shell和环境变量都是在定义它们的Shell/进程中本地的:

环境变量可以持久化,而对于Shell变量,一旦你退出会话,它们就消失了。

注意:上面的示例只会改变你正在使用的Shell,在其他单独的Shell/Terminal中退出或重新启动后,你无法看到定义的变量,这符合进程本地性原则


如何使Shell变量持久化:

一种方法是修改~/.profile文件:

export SHELL_VAR=xyz

此设置是用户特定的,而不是系统范围的。对于系统范围内的环境变量,您可以将上述行添加到/etc/profile.d中的.sh文件中。

我强烈建议阅读此页面:EnvironmentVariables


1
可以这样说,“持久性”环境变量与导出的shell变量实际上没有任何区别。唯一的区别在于它们存储的位置不同。持久性环境变量被写入(然后从非易失性介质,即磁盘中读取)。这是在一个位置(即~/.profile),当shell加载时会自动读取。导出的shell变量相同,只是存在于易失性内存中,因此在重新启动(断电等)时会丢失。这正确吗? - Chris

15

它们的差异类似于Java类中私有字段和受保护字段之间的差异。

Java类的私有字段仅可以从该Java类进行访问。Java类的受保护字段可以从该Java类及其子类进行访问。

Shell变量只能从该Shell进程中进行访问。由该Shell导出的环境变量可以从该Shell进程及从该Shell创建的子进程进行访问。


0
除了其他答案中的信息外,环境变量不如shell变量灵活。
Shell变量可以是数组或关联数组,但环境变量只能是字符串。由子进程继承的环境仅仅是一系列的“name=value”字符串。没有对值进行解析,因此无法指示值应该是一个数组的方式。

-2

一个 shell 变量只是环境变量的一种特殊情况。 shell 变量从环境中继承,并根据使用的语法可能被复制到 shell 子进程的环境中: http://www.pixelbeat.org/docs/env.html


3
这不正确。你基本上颠倒了术语。显然在这个话题上有很多混淆,即使是老练的用户和coreutils开发者也是如此?:-/ Translated: 这是不正确的。你基本上把术语颠倒了。显然在这个话题上有很多混淆,甚至老练的用户和coreutils开发人员也有些困惑?:-/ - deltaray
2
我认为我没有颠倒术语。我的意思是,环境列表对于包括shell在内的所有进程都更为基础和存在。shell变量是一种特殊情况,它们是从环境列表中初始化的。 - pixelbeat
但是你可以创建不是环境变量的shell变量。当你执行foo=bar时,它会创建一个shell变量。当你执行export foo时,它就成为了一个环境变量。 - Barmar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接