UNIX环境变量
2023-05-28 14:01:43 阿炯

环境变量是一个动态命名的值,可以影响计算机上进程的行为方式。例如一个正在运行的进程可以查询TEMP环境变量的值,以发现一个合适的位置来存储临时文件,或者查询HOME或USERPROFILE变量,以找到运行该进程的用户所拥有的目录结构。简单来说是具有一对名称和值的变量。其值可以是文件系统上所有可执行程序的位置,默认的编辑器,系统本地化设置等。新用户可能觉得这种管理变量的方式有点混乱,但是环境变量提供了一种在多个程序和进程间共享配置的简单方式。

在所有 UNIX 和 类Unix系统(如Linux)或Windows下,每个进程都有其各自的环境变量设置。缺省情况下,当一个进程被创建时除开创建过程中的明确更改外,它继承了其父进程的绝大部分环境设置。在API层级上,使用fork和exec函数进行变量设置;或利用bash shell文件,使用特殊的命令调用来改变环境变量:通过Env 间接替代或者使用ENVIRONMENT_VARIABLE=VALUE <command> 标识。所有的UNIX操作系统 以及DOS 和Microsoft Windows 都使用环境变量,但是它们使用不同的环境变量名称。我们可以通过运行程序来访问环境变量的值,环境变量的例子包括:
PATH 罗列出 shell 搜索用户输入的执行命令所在的目录。
HOME (类Unix系统,下同) 和 userprofile (Microsoft Windows) 表示用户的家目录在文件系统中的位置。
TERM 指定使用终端或虚拟终端 的类型 (如, vt100 或 终端)。
CVS_RSH 该选项可用于 ext 方式中指明 cvs 客户端寻找远端 shell 的路径,用作连接 cvs 服务器和以更高的优先权覆盖 $CVS_RSH 环境变量中指定的路径。
MAIL 当前用户的邮件存放目录。

Shell 脚本和批处理文件使用环境变量来存储临时值,用于以后在脚本中引用,也用于传递数据和参数给子进程。在Unix系统中,一个在脚本或程序中更改的环境变量值只会影响该进程,亦可能影响其子进程。其父进程和无关进程将不受影响。在DOS中,更改或删除一个批处理文件中的环境变量值将改变变量的期限命令的存在。

在Unix系统通过初始化脚本启动时,环境变量通常会在此时被初始化,因此会被系统中的其它进程所继承。用户可以而且经常添加环境变量到他们使用的shell脚本中。在Windows系统中,环境变量存储在 Windows 注册表中。

coreutils软件包含程序 printenv 和 env,用于显示当前环境变量的值:
$ printenv
$ printenv -0
$ printenv VARIABLE_NAME
$ echo $VARIABLE_NAME

注意:一些环境变量是属于特定用户的,比较一般用户和 root 用户的 printenv 的输出就可以看到其中的差异。

工具 env 可以用指定的环境变量执行一个命令。下面例子把环境变量 EDITOR 设置为 vim 然后执行命令 xterm,这个操作不会影响全局环境变量 EDITOR。
$ env EDITOR=vim xterm

shell 内置的set 命令可以设置 shell 选项值以及位置参数,或显示 shell 变量的名称和值。

每个进程都把它们的环境变量保存在 /proc/<PID>/environ 文件中,此文件包含用 nul (\x0) 字符分隔的键值对。用 sed 可以获得用户可读的内容,如:sed 's:\x0:\n:g' /proc/$PID/environ。

为了避免过多的环境设置,应该限制变量的作用域;图形会话和 systemd 服务要求在明确的位置设置环境变量。变量的作用域可以分为:
全局:任何用户运用的所有程序,不包含 systemd 服务。
按用户:某个用户运行的程序,不包含用户 systemd 服务或图形程序。

清除环境变量

1.将对应的变量的值置空:export LC_ALL=
2.使用unset指令取消定义:unset VARIABLE
3.反导出:export -n VARIABLE


全局

使用 shell 初始化文件

大多数 Linux 发行版告诉您在 /etc/profile 或其他位置更改或添加环境变量定义。请记住,还有一些特定于包的配置文件,其中包含变量设置,比如 /etc/locale.conf. 确保维护和管理环境变量,并注意可能包含环境变量的大量文件。原则上,任何 shell 脚本都可以用于初始化环境变量,但按照传统的 UNIX 约定,这些语句只应出现在某些特定的文件中。

下列文件可用于定义系统上的全局环境变量,每个文件都有不同的限制:
/etc/environment 被 pam_env 模块使用,与 shell 无关,所以无法使用脚本或通配符展开。此文件仅接受 variable=value 键值对格式。
/etc/profile 仅初始化登录 shell 的变量。但它可以执行脚本(比如/etc/profile.d/中的脚本) 并支持所有兼容 Bash 的 shell。

特定于 shell 的配置文件 - Shell 的全局配置文件,初始化变量并运行脚本。例如 Bash#Configuration files 或 Zsh#Startup/Shutdown files。

使用 pam_env

PAM 模块 pam_env(8) 从以下文件中按顺序加载要在环境中设置的变量:/etc/security/pam_env.conf 和 /etc/environment。
注意: 这些文件在其他文件之前读取,特别是 ~/.profile, ~/.bash_profile and ~/.zshenv 之前。
警告: 读取 ~/.pam_environment 已被弃用,不再起作用。

/etc/environment 必须由每行单独的一个 VARIABLE=value 键值对组成,例如:
EDITOR=nano

/etc/security/pam_env.conf 使用以下格式:
VARIABLE [DEFAULT=value] [OVERRIDE=value]

@{HOME} 和 @{SHELL} 是特殊的变量,展开到 /etc/passwd 中的定义。以下示例说明了如何将 HOME 环境变量展开到另一个变量:
XDG_CONFIG_HOME   DEFAULT=@{HOME}/.config

注意: 变量 ${HOME} 和 ${SHELL} 默认是未设置的,并不链接到 HOME 和 SHELL 环境变量。

该格式还允许在其它变量值中使用 ${VARIABLE} 展开已定义的变量,如下所示:
GOPATH DEFAULT=${XDG_DATA_HOME}/go

VARIABLE=value 键值对也是允许的,但不支持变量展开。


按用户

有时并不希望定义全局环境变量,比如要把 /home/my_user/bin 加入 PATH 变量但是不影响其它用户。本地环境变量可以在下面文件定义:
shell 的用户配置文件,例如 Bash#Configuration files 或 Zsh#Startup/Shutdown files.
systemd 用户环境变量 读取自 ~/.config/environment.d/*.conf .

要修改本地用户的 PATH 变量,将以下内容加入 ~/.bash_profile
export PATH="${PATH}:/home/my_user/bin"
export VARIABLE_NAME=value

要更新变量,重新登录或 source 文件:$ source ~/.bash_profile

注意:dbus 守护进程和 systemd 用户实例不会继承任何 .bashrc 等文件定义的环境变量,这意味着 dbus 启动的程序如 GNOME Files 默认不会使用这些变量。

图形环境

如果环境变量仅影响图形应用程序,您可能希望仅通过在图形会话中设置它来限制其范围。

Xorg 会话

修改 Xorg 会话环境的过程取决于其启动方式:
大多数显示管理器读取 xprofile.
startx 和 SLiM 执行 xinitrc.
XDM 执行 ~/.xsession;请参考 XDM#Defining the session.
SDDM 为登录 shell 读取额外启动脚本,比如 ~/.bash_profile 为 bash 或 ~/.zprofile 和 ~/.zlogin 为 zsh [1]

虽然脚本的结尾取决于它是哪个文件,且任何高级语法都取决于所使用的 shell,但基本用法是通用的:
~/.xprofile, ~/.xinitrc, or ~/.xsession
...
export GUI_VAR=value

Wayland 会话

由于 Wayland 不启动任何 Xorg 相关文件,因此 GDM 和 KDE Plasma 读取 systemd 用户环境变量。
~/.config/environment.d/envvars.conf
GUI_VAR=value


按会话

有时需要更严格的定义,可能希望从创建的特定目录临时运行若干可执行文件,而不必键入每个文件的绝对路径,也不必在运行 shell 配置文件所需的短时间内编辑 shell 配置文件。这种情况下可以用 export或set 命令在当前会话中定义 PATH 变量。只要不退出登录,PATH 变量就会一直生效。增加 PATH 到一个会话:
$ export PATH="${PATH}:/home/my_user/tmp/usr/bin"


示例

以下部分列出了 Linux 系统使用的一些常见环境变量,并描述了它们的值。

XDG_CURRENT_DESKTOP 是一个 freedesktop.org 变量,包含冒号分隔的字符串列表,标识当前 desktop environment. 活跃开发中环境的标准化值有 GNOME, GNOME-Flashback, KDE, LXDE, LXQt, MATE, TDE, Unity, XFCE, EDE, Cinnamon, 和 Pantheon.

Cinnamon 的注册时间比其他桌面环境晚. 因此,一些软件依旧使用注册前的值 X-CINNAMON, 比如 Qt 最新的6.3版本.

XDG_SESSION_DESKTOP 类似于 XDG_CURRENT_DESKTOP, 但只允许单个字符串。尽管名字包含 XDG,但它并没有由 freedesktop.org 标准化。

DE 是一个过时的变量,表明使用的桌面环境。没有权威的文档说明可能的值,但 xdg-utils 为许多桌面环境提供了参考。

DESKTOP_SESSION 类似于 DE,但是用于 LXDE 桌面环境:当 DESKTOP_SESSION 设置为 LXDE, xdg-open 会使用 pcmanfm 文件关联。

WINDOW_MANAGER 变量有时用于选择桌面环境要使用的 window manager,与其他变量不同,这里的变量是由已经选择的显示管理器或桌面环境设置的,供其他程序读取。

PATH 包含以冒号分隔的目录列表,系统在其中查找可执行文件。当一个一般命令 (例如 ls, systemctl 或 pacman) 由 shell 解释时 (如 bash 或 zsh), shell 从列表包含的目录中寻找与命令同名的可执行程序并执行。要运行不在 PATH 中的应用程序,必须给出可执行程序的相对或绝对路径,例如 ./a.out 或 /bin/ls.

注意: 安全起见,建议不要将当前工作目录 (.) 加入 PATH,因为它可能欺骗用户执行恶意命令。

HOME 包含当前用户主目录的路径。应用程序可以使用此变量将配置文件等与运行它的用户相关联。

PWD 包含工作目录的路径。

OLDPWD 包含前一个工作目录的路径,即执行最后一个 cd 之前的 PWD 的值。

TERM 包含正在运行的终端类型,例如 xterm-256color. 它由运行在终端中,希望使用终端特定功能的程序使用。

MAIL 包含传入电子邮件的位置。传统的设置是 /var/spool/mail/$LOGNAME.

ftp_proxy 和 http_proxy 分别包含 FTP 和 HTTP 代理服务器:Bash Proxy 设置


MANPATH 包含以冒号分隔的目录列表,man 命令在其中搜索手册页。

注意: 在 /etc/profile中,有一条注释说 "Man 比我们更擅长解决这个问题", 因此该变量通常不设置。请参考 manpath(5).

INFODIR 包含以冒号分隔的目录列表,info 命令在其中搜索信息页,比如 /usr/share/info:/usr/local/share/info

TZ 可用于为用户设置与系统区域不同的时区。/usr/share/zoneinfo/ 中列出的时区可作参考,例如 TZ=":/usr/share/zoneinfo/Pacific/Fiji". 当 TZ 变量指向 zoneinfo 文件时,应以冒号开头 GNU 手册。

Locale相关的语言环境变量。

程序依赖库变量环境:LD_LIBRARY_PATH、LD_PRELOAD等。


默认程序

SHELL 包含用户 首选 shell 的路径。请注意,这不一定是当前运行的 shell。在没有值的情况下,Bash 将自动将此变量设置为 /etc/passwd中定义的用户登录 shell,如果无法确定,则将此变量设为 /bin/sh.

PAGER 包含运行用于列出文件内容的程序的命令,例如 /bin/less。

EDITOR 包含运行用于编辑文件的轻量级程序的命令,例如 /usr/bin/nano. 本例中,你可以编写 X 下的gedit 或 nano 的交互式切换:
 [ -n "$DISPLAY" ] && export EDITOR=gedit || export EDITOR=nano

VISUAL 包含运行完整编辑器的命令,该编辑器用于更高要求的任务,如编辑邮件 (例如 vi, vim, emacs 等)。

BROWSER 包含 web 浏览器的路径。有助于在交互式 shell 配置文件中进行设置,以便根据图形环境的可用性对其进行动态更改,例如 X:
[ -n "$DISPLAY" ] && export BROWSER=firefox || export BROWSER=links


Common Environment Variables

BASHOPTS: The list of command line options that were used when bash was launched.
BASH_VERSION: The version of bash.
COLUMNS: The width of the terminal in columns.
DIRSTACK: The stack of directories for use with the pushd and popd commands.
HISTFILESIZE: The maximum number of lines of command history that can be written to the history file.
HISTSIZE: The maximum number of lines of command history allowed to be stored in memory. If you go past this number, previously remembered commands are overwritten in memory. When you close your terminal window, the command history is written to the history file.
HOME: The current user's home directory.
HOSTNAME: The name of the computer.
IFS: The internal field separator that is used to parse user input. The default value is a space.
LANG: The current language and localization settings, including character encoding.
LOGNAME: The name of the current user.
LS_COLORS: This defines the codes that are used to add color to the output from ls.
MAIL: The path to the current user's Linux mailbox.
OLDPWD: The previous working directory.
PS1: The primary command prompt definition. This defines what the prompt in your terminal window looks like.
PATH: A colon-separated list of directories that are searched, in order, for a matching command or application when you type a command into the shell.
PWD: The current working directory.
SHELL: The name of your default shell path.
TERM: The type of terminal that is emulated when you run a shell.
UID: The user identifier of the current user.
USER: The current logged-in user.
_: The most recently executed command. If you use printenv to list this, it’ll always be printenv.


参考来源:

UbuntuEnvironmentVariables

ArchLinux环境变量