Bash 环境变量的那些事
创始人
2024-03-02 01:28:34
0

初学者可以在此教程中了解环境变量。

bash 变量,尤其是讨厌的环境变量,已经是一个老生常谈的话题了。我们也更应该对它有一个详细的了解,让它为我们所用。

下面就打开终端,开始吧。

环境变量

HOME (LCTT 译注:双关语)除了是你脱下帽子惬意休息的地方,同时也是 Linux 中的一个变量,它是当前用户主目录的路径:

echo $HOME

以上这个命令会显示当前用户的主目录路径,通常都在 /home/ 下。

顾名思义,变量的值是可以根据上下文变化的。实际上,Linux 系统中每一个用户的 HOME 变量都是不一样的,当然你也可以这样自行更改 HOME 变量的值:

HOME=/home//Documents

以上这个命令将会把 HOME 变量设置为你的 Documents 目录。

其中有三点需要留意:

  1. = 符号和其两侧的内容之间不加空格。空格在 shell 中有专门的意义,不能随意地在任何地方添加空格。
  2. 如果你需要对变量进行赋值,只需要使用变量名称就可以了。但如果需要读取或者使用变量的值,需要在变量前面加上一个 $ 号。
  3. 更改 HOME 变量具有一定的风险。有很多程序是依赖于 HOME 变量的,更改 HOME 变量可能会导致一些不可预见的结果。例如,如果按照上面的方式更改了 HOME 变量,然后执行不带有任何参数的 cd 命令,在通常情况下,会跳转到用户的主目录下,但在这个时候,会跳转到 HOME 变量指定的目录下。

上面第 3 点中环境变量的更改并不是持久有效的,在终端关闭后重新打开终端,又或者是新建一个终端,执行 echo $HOME 命令输出的仍然会是初始的值,而不是重新自定义的值。

在讨论如何持久地更改一个环境变量之前,我们先来看一下另一个比较重要的环境变量。

PATH 变量

PATH 变量中存放了一系列目录,而且是放置了可执行程序的目录。正是由于 PATH 变量的存在,让你不需要知道应用程序具体安装到了什么目录,而 shell 却可以正确地找到这些应用程序。

如果你查看 PATH 变量的值,大概会是以下这样:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin

每两个目录之间使用冒号 : 分隔。如果某个应用程序的所在目录不在 PATH 变量中,那么运行的时候就需要声明应用程序的目录让 shell 能够找到。

/home//bin/my_program.sh

例如以上命令就会执行当前用户 bin/ 目录下的 my_program.sh 文件。

有一个常见的问题:如果你不希望弄乱系统的 bin/ 目录,同时也不希望你自己的文件被其它人运行,还不想每次运行的时候都要输入完整的路径,那么,你可以在你的主目录中创建一个独立的 bin/ 目录:

mkdir $HOME/bin

然后将这个目录添加到 PATH 变量中:

PATH=$PATH:$HOME/bin

然后 /home//bin/ 目录就会出现在 PATH 变量中了。但正如之前所说,这个变更只会在当前的 shell 生效,当前的 shell 一旦关闭,环境变量的值就又恢复原状了。

如果要让变更对当前用户持续生效,就不能在 shell 中直接执行对应的变更,而是应该将这些变更操作写在每次启动 shell 时都会运行的文件当中。这个文件就是当前用户主目录中的 .bashrc 文件。文件名前面的点号表明这是一个隐藏文件,执行普通的 ls 命令是不会将这个文件显示出来的,但只要在 ls 命令中加入 -a 参数就可以看到这个文件了。

你可以使用诸如 kategeditnano 或者 vim 这些文本编辑器来打开 .bashrc 文件(但不要用 LibreOffice Writer,它是一个文字处理软件,跟前面几个文字编辑器完全不同)。打开 .bashrc 文件之后,你会看见里面放置了一些 shell 命令,是用于为当前用户设置环境的。

在文件的末尾添加新行并输入以下内容:

export PATH=$PATH:$HOME/bin

保存并关闭 .bashrc 文件,接下来你就会看到 export 语句的效果。执行以下的命令让刚才的修改立即生效:

source .bashrc

刚才执行的 source 命令让 .bashrc 文件在当前的 shell 立即生效,并且对于之后打开的 shell 都会有效。因此另一个等效的方法是退出并重新进入 shell,但这样也太麻烦了。

现在,你的 shell 就能自动寻找到 /home//bin/ 下的程序了,执行这个目录下的程序也不需要完整地写出程序的路径。

自定义变量

当然,你也可以定义自己的变量。刚才我们看到的变量名称都是全大写的,实际上变量名称的定义还是比较灵活的

定义新变量的过程非常直观,直接对它赋值就可以了:

new_variable="Hello"

然后可以用以下的方式读取到已定义变量的值:

echo $new_variable

程序的正常工作离不开各种变量,例如要将某个选项设置为打开,又或者让程序找到所需的代码库,都需要使用变量。在 bash 中运行程序的时候会生成一个子 shell,这个子 shell 和执行原程序的父 shell 并不是完全一样的,只是继承了父 shell 的部分内容,而且默认是不继承父 shell 中的变量的。因为变量默认情况下是局部变量,出于安全原因,一个 shell 中的局部变量不会被另一个 shell 读取到,即使是子 shell 也不可以。

下面举一个例子。首先定义一个变量:

robots="R2D2 & C3PO"

然后执行:

bash

现在是在 bash shell 中创建了一个子 shell。

执行这个命令看看还能不能读取到刚才定义的变量:

echo $robots

你会发现读取不到。

还是在这个子 shell 中,为 robots 变量赋一个不同的值:

robots="These aren't the ones you are looking for"

再读取一次:

$ echo $robots
These aren't the ones you are looking for

退出这个子 shell:

exit

然后再看一下现在 robots 变量的值:

$ echo $robots
R2D2 & C3P0

这一个特性可以有效避免配置过程中产生混乱,同时也会导致一个问题:如果程序中需要设置变量,但却由于子 shell 的原因无法正常访问到这个变量,该如何解决呢?这个时候就需要用到 export 了。

重复一次刚才的过程,但这一次不是通过 robots="R2D2 & C3PO" 方式来设置变量,而是使用 export 命令:

export robots="R2D2 & C3PO"

现在你会发现,在进入子 shell 之后,robots 变量的值仍然是最初赋予的值。

要注意的是,尽管子 shell 会继承通过 export 导出的变量,但如果在子 shell 中对这个变量重新赋值,是不会影响到父 shell 中对应变量的。

如果要查看所有通过 export 导出的变量,可以执行以下命令:

export -p

自定义的变量会显示在这个列表的末尾。这个列表中还有一些常见的变量:例如 USER 的值是当前用户的用户名,PWD 的值是当前用户当前所在的目录,而 OLDPWD 的值则是当前用户上一个访问过的目录。因此如果执行:

cd -

就会切换到上一个访问过的目录,那是因为 cd 命令读取到了 OLDPWD 变量的值。

你也可以使用 env 命令查看所有环境变量。

如果要取消导出一个变量,可以加上 -n 参数:

export -n robots

接下来

了解过环境变量的知识之后,你已经到达了可能对自己和他人造成危险的水平,接下来就需要了解如何通过使用别名来让环境变得更安全、更友好以保护自己了。


via: https://www.linux.com/blog/learn/2018/12/bash-variables-environmental-and-otherwise

作者:Paul Brown 选题:lujun9972 译者:HankChow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关内容

编写CentOS系统下的B...
面对重复繁琐的服务器操作,手动输入命令效率低下且易出错。为了解决这...
2025-06-15 08:43:24
Vite的环境变量
环境变量和模式 环境变量 Vite 在一个特殊的 import.m...
2025-06-01 01:29:16
大数据开发中常用的shel...
内容目录一、date二、find三、awk四、cut五、if六、s...
2025-05-31 22:29:07
【Linux】环境变量介绍...
文章目录环境变量环境变量的概念PATH使程序可在命令行中直接运行环...
2025-05-31 19:30:26
shell常见面试题二
(8)、shell中case语法 #!...
2025-05-30 22:47:54
Shell 的变量功能
什么是变量?? 应该很好理解吧&#x...
2025-05-30 15:50:47

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
2024 开年,LLUG 和你... Hi,Linuxer,2024 新年伊始,不知道你是否已经准备好迎接新的一年~ 2024 年,Lin...
什么是 KDE Connect... 什么是 KDE Connect?它的主要特性是什么?它应该如何安装?本文提供了基本的使用指南。科技日...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...