引言
在本实验中,你将学习 Linux 中管理 shell 环境和配置的基础知识。你将从创建本地变量和环境变量开始,使用 echo
、export
和 env
等命令来理解它们在 shell 会话中的作用域和可用性的关键区别。
在此基础上,你将探索变量和别名在子 shell 中的继承方式。你还将学习如何使用 set -o allexport
选项控制变量的自动导出,以及如何通过修改 .bashrc
文件使自定义配置在会话之间持久化。
在本实验中,你将学习 Linux 中管理 shell 环境和配置的基础知识。你将从创建本地变量和环境变量开始,使用 echo
、export
和 env
等命令来理解它们在 shell 会话中的作用域和可用性的关键区别。
在此基础上,你将探索变量和别名在子 shell 中的继承方式。你还将学习如何使用 set -o allexport
选项控制变量的自动导出,以及如何通过修改 .bashrc
文件使自定义配置在会话之间持久化。
在本步骤中,你将学习如何创建和管理 shell 变量。在 Zsh 等 Linux shell 中,变量用于存储信息。主要有两种类型:本地变量和环境变量。
我们将使用 echo
、export
和 env
等命令来操作它们。所有命令都将在终端中执行。
首先,让我们创建一个本地变量。在你的终端中,它应该已经在 ~/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 环境的结构以及脚本如何执行至关重要。我们将测试前一步骤中的变量 flower
和 nut
是否会被子 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
启动文件中,从而使你的环境自定义设置永久生效。