环境变量
环境变量是一个包含一个或多个应用程序使用的数据的命名对象。简单来说,它是一个有名称和值的变量。环境变量的值可以是文件系统中所有可执行文件的位置、应该使用的默认编辑器,或者系统区域设置。初次接触 Linux 的用户可能会觉得这种管理设置的方式有点难以驾驭。然而,环境变量提供了一种在 Linux 中共享多个应用程序和进程之间配置设置的简单方法。
工具
coreutils 包包含 printenv 和 env 程序。要列出当前环境变量及其值
$ printenv
env 工具可以用于在修改后的环境中运行命令。以下示例将启动 xterm,并将环境变量 EDITOR 设置为 vim。这不会影响全局环境变量 EDITOR。
$ env EDITOR=vim xterm
set(1p) shell 内建命令允许你更改 shell 选项的值,设置位置参数,并显示 shell 变量的名称和值。
每个进程将其环境存储在 /proc/$PID/environ 文件中。该文件包含由空字符 (\x0) 分隔的每个键值对。可以使用 sed 来获得更易读的格式,例如 sed 's:\x0:\n:g' /proc/$PID/environ。
定义变量
为了避免不必要地污染环境,你应该尽量限制变量的范围。实际上,图形会话和 systemd 服务要求你在特定位置设置变量才能生效。环境变量的范围被分解为它们影响的上下文
- 全局:任何用户运行的所有程序,不包括 systemd 服务。
- 按用户:某个特定用户运行的所有程序,不包括用户 systemd 服务(参见 systemd/User#环境变量)或图形应用程序(参见 #图形环境)。
全局
使用 shell 初始化文件
大多数 Linux 发行版会告诉你更改或添加环境变量定义在 /etc/profile 或其他位置。请记住,还有包含变量设置的特定于包的配置文件,例如 /etc/locale.conf。请确保维护和管理环境变量,并注意可能包含环境变量的众多文件。原则上,任何 shell 脚本都可以用于初始化环境变量,但遵循传统的 UNIX 约定,这些语句应该只存在于某些特定文件中。
以下文件可用于定义系统上的全局环境变量,每个文件都有不同的限制
/etc/environment被 pam_env 模块使用,并且与 shell 无关,因此不能使用脚本或 glob 扩展。该文件只接受variable=value对。/etc/profile仅为登录 shell 初始化变量。但是,它会运行脚本(例如/etc/profile.d/中的脚本),并且可以被所有 Bourne shell 兼容的 shell 使用。- 特定于 shell 的配置文件 - 你 shell 的全局配置文件,初始化变量并运行脚本。例如 Bash#配置文件(例如
~/.bashrc)或 Zsh#启动/关闭文件(例如~/.zshrc)。
以下 Bash 辅助函数可用于将多个目录追加到 PATH 环境变量。将函数添加到定义环境变量的文件顶部(例如 ~/.bashrc)。该函数只会添加实际存在于文件系统中的目录,并且会避免创建重复条目。
add_paths() {
for d in "$@"; do
[[ -d "$d" && ! "$PATH" =~ (^|:)$d(:|$) ]] && PATH="$PATH:$d"
done
}
add_paths ~/bin ~/scripts
大多数 shell(包括 Bash、Zsh 和 fish)允许使用 export 命令将变量添加到环境中。这允许在通用文件(如 ~/my-environment.sh)中定义环境变量。
~/my-environment.sh
export EDITOR=vim export XDG_CACHE_HOME="$HOME/.cache" export XDG_CONFIG_HOME="$HOME/.config" export XDG_DATA_HOME="$HOME/.local/share" export XDG_STATE_HOME="$HOME/.local/state"
然后可以从 shell 启动文件中 source 此文件。
~/.bashrc
source ~/my-environment.sh
~/.config/fish/config.fish
source ~/my-environment.sh
使用 pam_env
PAM 模块 pam_env(8) 按顺序从以下文件中加载要设置在环境中的变量:/etc/security/pam_env.conf 和 /etc/environment。
- 这些文件在读取其他文件之前被读取,尤其是在读取
~/.profile、~/.bash_profile和~/.zshenv之前。 - 已弃用的
~/.pam_environment不再被读取。参见 FS#68945。
/etc/environment 必须包含单独一行的简单 VARIABLE=value 对,例如
/etc/environment
EDITOR=nano
/etc/security/pam_env.conf 具有以下格式
/etc/security/pam_env.conf
VARIABLE [DEFAULT=value] [OVERRIDE=value]
@{HOME} 和 @{SHELL} 是特殊变量,分别扩展为在 /etc/passwd 中定义的值。以下示例说明如何将 HOME 环境变量扩展到另一个变量。
/etc/security/pam_env.conf
XDG_CONFIG_HOME DEFAULT=@{HOME}/.config
${HOME} 和 ${SHELL} 不与 HOME 和 SHELL 环境变量相关联,它们默认不设置。该格式还允许使用 ${VARIABLE} 将已定义的变量扩展到其他变量的值中,如下所示。
/etc/security/pam_env.conf
GOPATH DEFAULT=${XDG_DATA_HOME}/go
也允许 VARIABLE=value 对,但在这些对中不支持变量扩展。有关更多信息,请参见 pam_env.conf(5)。
每个用户
你不一定希望全局定义环境变量。例如,你可能想将 /home/my_user/bin 添加到 PATH 变量,但又不希望系统上的所有其他用户也在他们的 PATH 中包含它。可以在许多不同的文件中定义本地环境变量。
- 你 shell 的用户配置文件,例如 Bash#配置文件 或 Zsh#启动/关闭文件。
- 除非你将变量的范围限制在您打开的终端(例如,仅命令行应用程序),否则你需要修改登录 shell。
- systemd 用户环境变量从
~/.config/environment.d/*.conf读取。
要为本地使用将目录添加到 PATH,请将以下内容放入 ~/.bash_profile。
export PATH="${PATH}:/home/my_user/bin"
要更新变量,请重新登录或 source 文件:$ source ~/.bash_profile。
~/.bashrc 等位置设置的任何环境变量。这意味着,例如,dbus 激活的程序(如 GNOME Files)默认不会使用它们。参见 systemd/User#环境变量。export -p 来查看为用户会话声明的全局和本地环境变量。图形环境
如果环境变量仅影响图形应用程序,你可能希望通过仅在图形会话中设置它来限制其范围。按范围递减的顺序:
- #每个 Xorg 会话 和 #每个 Wayland 会话 影响整个图形会话,当然包括 DE。
- #每个桌面环境会话 影响在图形会话中启动的应用程序,可能包括 DE 本身。
- #每个应用程序 只影响特定图形应用程序。
每个桌面环境会话
某些图形环境(例如 KDE Plasma)支持在登录时执行 shell 脚本:这些脚本可用于设置环境变量。例如,参见 KDE#自启动。
每个 Xorg 会话
修改 Xorg 会话环境的过程取决于它的启动方式。
- 大多数 显示管理器 source xprofile。
- startx 和 SLiM 执行 xinitrc。
- XDM 执行
~/.xsession;参见 XDM#定义会话。 - LightDM[1] 和 SDDM[2] 另外还会 source 登录 shell 的启动脚本,例如 bash 的
~/.bash_profile或 zsh 的~/.zprofile和~/.zlogin。
尽管脚本的结尾取决于它是哪个文件,并且任何高级语法都取决于使用的 shell,但基本用法是通用的。
~/.xprofile, ~/.xinitrc, or ~/.xsession
... export GUI_VAR=value ...
每个 Wayland 会话
由于 Wayland 不会启动任何与 Xorg 相关的 Xorg 文件,GDM 和 KDE Plasma 则 source systemd 用户环境变量。
~/.config/environment.d/envvars.conf
GUI_VAR=value
其他支持 Wayland 会话的显示管理器(例如 SDDM)目前不提供对此的直接支持。但是,LightDM 和 SDDM 也会为 Wayland 会话 source 登录 shell 的启动脚本。
greetd 也 source /etc/profile 和 ~/.profile - 此行为由其 source_profile 设置控制,默认启用。
如果你的显示管理器 source 了 ~/.bash_profile 这类启动脚本,并且你想使用 environment.d,你可以这样做:
~/.bash_profile
# use systemd-environment-d-generator(8) to generate environment, and export those variables set -o allexport source <(/usr/lib/systemd/user-environment-generators/30-systemd-environment-d-generator) set +o allexport
/usr/lib/systemd/user-environment-generators 中的其他生成器,如 60-flatpak,可能不会引用环境变量的值。在这种情况下,输出应使用 export -- "$(/usr/lib/systemd/user-environment-generators/60-flatpak)" 来 source。每个应用程序
要仅为特定应用程序而不是整个会话设置环境变量,请编辑应用程序的 .desktop 文件。有关说明,请参见 Desktop entries#修改环境变量。
对于 Steam 游戏,你可以通过编辑其启动选项来配置程序的运行环境;参见 Steam#启动选项。
每个会话或 shell
有时只需要临时变量。一个人可能希望临时从特定目录运行可执行文件,而不必每次都输入完整的 PATH,或者在简短的临时 shell 脚本中使用 PATH。
例如,要将特定于会话的目录添加到 PATH,请使用:
$ export PATH="${PATH}:/home/my_user/tmp/usr/bin"
要仅将特定于 shell 的目录添加到 PATH,请使用:
$ PATH="${PATH}:/home/my_user/tmp/usr/bin"
在 Bash 中,PATH 默认已导出,因此上述两者在被覆盖之前都会对子进程可见。为了更好地说明导出变量和非导出变量之间的区别,请考虑以下内容:
$ MYVAR="shell-only" $ bash -c 'echo $MYVAR' # prints nothing $ export MYVAR="session-wide" $ bash -c 'echo $MYVAR' # prints: session-wide
示例
下一节列出了 Linux 系统使用的许多常见环境变量,并描述了它们的值。
XDG_CURRENT_DESKTOP是一个 freedesktop.org 变量,包含一个冒号分隔的字符串列表,表示当前 桌面环境 标识为 [3]。积极开发的桌面环境的标准化值包括GNOME、GNOME-Flashback、KDE、LXDE、LXQt、MATE、TDE、Unity、XFCE、EDE、Cinnamon、Pantheon和DDE[4]。
XDG_SESSION_DESKTOP与XDG_CURRENT_DESKTOP类似,但只允许一个字符串。尽管有这个名字,它不是由 freedesktop.org 标准化的。
DE是一个旧变量,指示正在使用的桌面环境。没有关于可能值的中央文档,但 xdg-utils 提供了许多桌面环境的参考。
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 代理服务器。
ftp_proxy="ftp://192.168.0.1:21" http_proxy="http://192.168.0.1:80"
MANPATH包含一个冒号分隔的目录列表,man 在其中搜索 man 页。
/etc/profile 中,有一条注释说“Man 比我们更擅长解决这个问题”,所以这个变量通常应该保持未设置。参见 manpath(5)。INFODIR包含一个冒号分隔的目录列表,info 命令在其中搜索 info 页,例如/usr/share/info:/usr/local/share/info。
TZ可用于设置一个与系统区域不同的用户区域。/usr/share/zoneinfo/中列出的区域可用作参考,例如TZ=":/usr/share/zoneinfo/Pacific/Fiji"。当将TZ变量指向区域信息文件时,根据 GNU 手册,它应该以冒号开头。
默认程序
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
BROWSER包含 Web 浏览器的路径。在交互式 shell 配置文件中设置它很有用,以便它可以根据图形环境(如 X)的可用性进行动态更改。
[ -n "$DISPLAY" ] && export BROWSER=firefox || export BROWSER=links
WAYLAND_DISPLAY 环境变量有条件地设置这些默认程序,前提是正在运行 Wayland 合成器。