Contents

在Linux中管理环境变量

1. 概述

每个 Linux 进程都有自己的一组环境变量,它从其父进程继承。例如,当我们在 shell 中执行命令时,该命令会继承 shell 的环境变量。

在本教程中,我们将了解如何使用envprintenvexport 管理这些变量。

虽然我们将使用 Bash,但本文中的所有示例也应该在其他 POSIX 兼容的 shell 中工作。

2. 全局环境变量

当我们启动一个 shell 时,我们使用一组预定义的环境变量创建我们的 shell。我们可以全局或按用户声明它们。

使用 Bash,我们在*/etc/profile中声明全局变量。但是,我们建议在它们自己的脚本文件中声明它们并将它们放在/etc/profile.d*中。Bash 会自动拾取这些。

全局变量影响系统中的所有用户。每个用户都可以通过在其主目录中创建*~/.profile*来为自己创建一组“全局”环境变量。

我们每天使用的最常见的环境变量之一是PATH变量。PATH包含我们的 shell 搜索可执行文件的位置列表。我们可以通过创建一个包含类似信息的*~/.profile来添加一些东西到我们的PATH*中:

PATH=$PATH:/path/to/executable/

在这里,我们实际上重新声明了PATH变量并将其值设置为PATH的当前值,并将*/path/to/executable/*添加到它。

在接下来的部分中,我们将描述最常用于管理环境变量的命令。让我们开始envprintenv

3. envprintenv

我们已经提到每个进程都在自己的环境中运行。通过提供额外的环境变量,我们可以使用env在修改后的环境中运行程序:

env CUSTOM_VAR=42 /path/to/script.sh

在此示例中,env将在一个环境中执行*/path/to/script.sh*,该环境是我们的 shell 环境的副本,其中CUSTOM_VAR作为添加的环境变量,值为42

实际上,env接受以空格分隔的变量列表。因此,我们可以添加多个变量:

env VAR_ONE=1 VAR_TWO=2 /path/to/script.sh

我们还可以通过在变量前面加上*-u*来取消设置或删除变量:

env -u PATH /path/to/script.sh

这将在当前环境的副本中运行我们的脚本,但没有PATH变量。 我们甚至可以在一个空的环境中运行我们的脚本:

env -i /path/to/scripts.sh

最后,不带参数运行env将打印当前环境中所有变量的列表。我们可以用printenv完成同样的事情:

[itcodingman@blogdemo ~]$ set
HOSTNAME=localhost.localdomain
TERM=xterm-256color
SHELL=/bin/bash
HISTSIZE=1000SSH_TTY=/dev/pts/0
USER=vagrant
MAIL=/var/spool/mail/vagrant
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin
PWD=/home/vagrant
LANG=en_US.UTF-8
HOME=/home/vagrant
LOGNAME=vagrant

我们还可以通过提供以空格分隔的变量名称列表来打印特定变量的值:

printenv HOSTNAME PATH HOME

这将打印:

localhost.localdomain
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin
/home/vagrant

4. export

我们不应该将环境变量与 shell 变量混淆。Shell 变量是仅适用于我们当前 shell 的变量,不会被我们执行的任何程序或脚本继承。

我们可以通过调用set来概览适用于当前 shell 的所有变量:

[itcodingman@blogdemo ~]$ set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
HOSTNAME=localhost.localdomain
TERM=xterm-256color
SHELL=/bin/bash
HISTSIZE=1000SSH_TTY=/dev/pts/0
USER=vagrant
MAIL=/var/spool/mail/vagrant
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin
PWD=/home/vagrant
LANG=en_US.UTF-8 HOME=/home/vagrant
LOGNAME=vagrant

我们可以看到特定于 Bash 的 shell 变量以及我们在使用printenv之前打印的所有环境变量。

Shell 变量不被子进程继承,但我们可以将它们导出以使其可见。我们可以通过一个例子来最好地解释这一点。

首先,让我们创建一个新的 shell 变量:

CUSTOM_VAR=42

我们可以使用echo 打印变量的值:

echo "Custom var value: $CUSTOM_VAR"
42

为了验证变量不能从子进程中看到,让我们将echo命令放在我们将命名为 print_custom_var.sh的脚本中:

#!/bin/bash
echo "Custom var value: $CUSTOM_VAR"

当我们运行脚本时,输出将是:

./print_custom_var.sh
Custom var value:

我们的脚本看不到CUSTOM_VAR的值,因为 脚本不存在CUSTOM_VAR。我们可以使用export使其对子进程可见:

export CUSTOM_VAR

现在,让我们再次运行脚本:

./print_custom_var.sh
Custom var value: 42