在 Linux 中管理 Shell 环境和配置

CompTIACompTIABeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

引言

在本实验中,你将学习 Linux 中管理 shell 环境和配置的基础知识。你将从创建本地变量和环境变量开始,使用 echoexportenv 等命令来理解它们在 shell 会话中的作用域和可用性的关键区别。

在此基础上,你将探索变量和别名在子 shell 中的继承方式。你还将学习如何使用 set -o allexport 选项控制变量的自动导出,以及如何通过修改 .bashrc 文件使自定义配置在会话之间持久化。

创建和区分本地变量与环境变量

在本步骤中,你将学习如何创建和管理 shell 变量。在 Zsh 等 Linux shell 中,变量用于存储信息。主要有两种类型:本地变量和环境变量。

  • 本地变量(或 shell 变量)仅在你创建它的 shell 中可用。
  • 环境变量不仅在当前 shell 中可用,而且在从该 shell 启动的任何子进程中也可用。

我们将使用 echoexportenv 等命令来操作它们。所有命令都将在终端中执行。

首先,让我们创建一个本地变量。在你的终端中,它应该已经在 ~/project 目录,输入以下命令来创建一个名为 flower 的变量并为其赋值 rose。请注意,等号 (=) 两侧不能有空格。

flower=rose

为了验证变量是否已创建,你可以使用 echo 命令打印其值。变量名前的美元符号 ($) 告诉 shell 将变量替换为其值。

echo $flower

你应该会在终端看到变量的值被打印出来:

rose

现在,让我们检查一下这个本地变量是否是 shell 环境的一部分。env 命令会列出所有环境变量。我们可以将它的输出通过管道传递给 grep 来搜索我们的变量。

env | grep flower

此命令将不会产生任何输出。这是预期的结果,它证实了 flower 是一个本地变量,而不是环境变量。

接下来,让我们创建一个环境变量。过程类似,但我们使用 export 命令。此命令会创建一个变量并将其标记为传递给当前 shell 的所有子进程。让我们创建一个名为 nut 的环境变量,值为 almond

export nut=almond

让我们像之前一样用 echo 来验证它。

echo $nut

该命令将输出 nut 变量的值:

almond

现在,让我们再次使用 env 命令检查它是否存在于环境中。

env | grep nut

这次,命令会找到并显示该变量,证实 nut 是一个环境变量:

nut=almond

你现在已经成功创建了一个本地变量和一个环境变量,并看到了 shell 环境如何处理它们的根本区别。我们将保留这些变量以供后续步骤使用。

测试子 shell 中的变量和别名继承

在本步骤中,你将探索当你从当前 shell 启动一个新 shell 时,变量和别名的行为。这个新 shell 称为“子 shell”,而原始 shell 是“父 shell”。这个概念对于理解 shell 环境的结构以及脚本如何执行至关重要。我们将测试前一步骤中的变量 flowernut 是否会被子 shell“继承”。

首先,让我们确定当前父 shell 的进程 ID (PID)。Linux 中的每个进程都有一个唯一的 PID。你可以使用 echo $$ 命令查看它。

echo $$

你的输出将是一个数字,这是你当前 shell 的 PID。例如:

123

现在,通过简单地输入 zsh 并按 Enter 来启动一个子 shell。这会在你当前的 shell 中创建一个新的 shell 进程。

zsh

你现在处于一个新的 shell 会话中。为了确认这一点,我们可以使用 ps -f 命令,它会显示详细的进程信息,包括父进程 ID (PPID)。

ps -f

查看输出。你将看到两个 zsh 进程。新的 zsh 进程的 PID 应该有一个 PPID,它匹配你之前记下的父 shell 的 PID。

UID          PID    PPID  C STIME TTY          TIME CMD
labex        123       1  0 10:00 pts/0    00:00:00 zsh
labex        456     123  0 10:01 pts/0    00:00:00 zsh
labex        457     456  0 10:01 pts/0    00:00:00 ps -f

在这个例子中,新 shell (PID 456) 是原始 shell (PPID 123) 的子进程。

现在,让我们测试变量。在这个子 shell 中,尝试显示本地变量 flower 的值。

echo $flower

该命令没有产生任何输出。这是因为本地变量仅限于它们被创建的 shell,并且不会被子 shell 继承。

接下来,检查环境变量 nut

echo $nut

这次,shell 打印了变量的值:

almond

这表明环境变量不像本地变量那样,会被子 shell 继承。

现在,使用 exit 命令返回到父 shell。

exit

你现在回到了原始 shell。让我们用一个别名进行类似的测试。别名是命令的快捷方式。创建一个名为 ldetc 的别名,它执行 ls -ld /etc

alias ldetc='ls -ld /etc'

通过输入 alias 来验证别名是否已创建。

alias ldetc

你应该会看到你的别名定义:

ldetc='ls -ld /etc'

现在,通过运行它来测试别名。

ldetc

该命令将执行 ls -ld /etc 并向你显示 /etc 目录的详细信息。

drwxr-xr-x 1 root root 4096 Oct 10 10:00 /etc

现在,打开另一个子 shell,看看别名是否被继承。

zsh

在新子 shell 中,尝试使用 ldetc 别名。

ldetc

你将收到一个错误消息,因为别名,就像本地变量一样,不会被子 shell 继承。

zsh: command not found: ldetc

返回到父 shell。

exit

最后,让我们通过使用 unalias 命令从父 shell 中删除别名来清理。

unalias ldetc

通过再次尝试列出它来验证其移除。

alias ldetc

没有任何输出。

这个练习向你展示了 shell 行为的一个关键原则:环境变量会被子进程继承,但本地变量和别名不会。

使用 set -o allexport 控制自动导出变量

在本步骤中,你将了解一个名为 allexport 的强大 shell 选项。通常情况下,当你创建一个变量时,你必须显式使用 export 命令将其设为环境变量。然而,通过启用 allexport 选项,你可以指示 shell 自动导出你定义的每一个新变量。这可以是一个方便的快捷方式,尤其是在所有变量都需要对子进程可用的脚本中。

Shell 选项是改变 shell 行为的内部设置。你可以使用 set -o [option_name] 来开启它们,并使用 set +o [option_name] 来关闭它们。

首先,让我们检查 allexport 选项的当前状态。你可以列出所有 shell 选项并使用 grep 过滤出 allexport

set -o | grep allexport

默认情况下,此选项是关闭的。输出将显示其状态为 off

allexport              off

现在,让我们开启 allexport 选项。

set -o allexport

通过再次运行检查命令来验证设置是否已更改。

set -o | grep allexport

这次,输出将确认该选项已开启 (on):

allexport              on

在启用 allexport 后,你创建的任何变量都将自动成为环境变量。让我们来测试一下。创建一个名为 truck 的新变量,而无需使用 export 命令。

truck=chevy

现在,使用 env 命令检查 truck 是否存在于环境中。

env | grep truck

你将看到 truck 变量已被列出,即使你没有使用 export。这是因为 allexport 选项是激活的。

truck=chevy

这个功能可能非常有用,但最好在你不再需要它时将其关闭,以避免无意中导出变量。让我们关闭 allexport

set +o allexport

最后,验证它已被关闭。

set -o | grep allexport

输出将再次显示该选项已关闭 (off)。

allexport              off

从现在开始,任何新变量的创建都将是本地变量,除非你显式使用 export 命令。

使用 .bashrc 文件持久化 Shell 选项

在本步骤中,你将学习如何使你的 shell 自定义设置永久生效。任何你设置的别名、函数或 shell 选项都是临时的,在你关闭终端会话时会丢失。要永久保存它们,你需要将它们添加到 shell 配置文件中。

虽然标题提到了 .bashrc,它是 Bash shell 的配置文件,但我们的实验环境使用的是 Zsh shell。Zsh 的等效配置文件是 ~/.zshrc。这个文件是一个脚本,每次你打开一个新的交互式 shell 时都会自动运行,使其成为存储个人设置的理想位置。

我们将通过使 noclobber shell 选项永久生效来实践这一点。noclobber 选项可以防止你在使用输出重定向 (>) 时意外覆盖现有文件。

首先,让我们使用 nano 文本编辑器将 noclobber 选项添加到你的 ~/.zshrc 文件中。~ 符号是你主目录 /home/labex 的快捷方式。

nano ~/.zshrc

此命令会在 nano 编辑器中打开 ~/.zshrc 文件。使用箭头键将光标移动到文件末尾,并添加以下行:

set -o noclobber

现在,保存文件并退出 nano。要做到这一点,按 Ctrl+O (Write Out),按 Enter 确认文件名,然后按 Ctrl+X 退出。

你现在回到了命令提示符。让我们检查一下 noclobber 选项在你当前的 shell 中是否处于活动状态。

set -o | grep noclobber

输出将是:

noclobber              off

为什么它是关闭的?因为你当前的 shell 会话尚未读取你刚刚对 ~/.zshrc 文件所做的更改。该文件仅在新 shell 启动时读取。

为了证明这一点,让我们启动一个新的子 shell。

zsh

你现在处于一个新的 shell 中。让我们在这里检查 noclobber 的状态。

set -o | grep noclobber

这次,输出将是:

noclobber              on

这证实了新 shell 正确读取了 ~/.zshrc 文件并应用了设置。现在,退出子 shell 以返回到你原来的父 shell。

exit

那么,如何在不关闭和重新打开的情况下将更改应用于你当前的 shell 呢?你可以使用 source 命令,它会在当前 shell 的上下文中读取并执行文件中的命令。

source ~/.zshrc

source 命令现在已经从你的配置文件中执行了 set -o noclobber 行。让我们验证一下 noclobber 在我们原来的 shell 中是否已开启。

set -o | grep noclobber

输出现在将是:

noclobber              on

你已成功学习了如何通过编辑 ~/.zshrc 文件来持久化 shell 设置,以及如何使用 source 命令将这些更改应用于你当前的会话。

总结

在本实验中,你学习了管理 Linux shell 环境的基础概念。你练习了创建本地变量(仅限于当前 shell)和环境变量(会被任何子进程继承)。诸如 echo 用于显示变量值、export 用于创建环境变量以及 env 用于列出它们等关键命令得到了应用。通过启动一个子 shell 来测试哪些变量和别名已成功从父 shell 传递下来,进一步探讨了继承的概念。

此外,你还探索了控制和持久化 shell 配置的方法。你使用了 set -o allexport 选项来自动导出所有后续定义的变量,从而简化了使它们可供子进程使用的过程。为了确保你的自定义变量、别名和 shell 选项在所有未来的终端会话中都可用,你学会了如何将这些配置添加到 .bashrc 启动文件中,从而使你的环境自定义设置永久生效。