环境变量

出自ArchWiki
(重定向自 Variable)

环境变量是一个命名的对象,其中包含一个或多个应用程序使用的数据。简单来说,它是一个带有名称和值的变量。环境变量的值可以是例如文件系统中所有可执行文件的位置、应使用的默认编辑器或系统区域设置。Linux 新手可能会觉得这种管理设置的方式有点难以管理。但是,环境变量提供了一种在 Linux 中多个应用程序和进程之间共享配置设置的简单方法。

实用程序

coreutils 软件包包含程序 printenvenv。列出当前带有值的环境变量

$ printenv
注意: 某些环境变量是用户特定的。通过比较非特权用户和 root 用户身份下 printenv 的输出来检查。

env 实用程序可用于在修改后的环境中运行命令。以下示例将启动 xterm,并将环境变量 EDITOR 设置为 vim。这不会影响全局环境变量 EDITOR

$ env EDITOR=vim xterm

shell 内置命令 set(1p) 允许您更改 shell 选项的值,设置位置参数以及显示 shell 变量的名称和值。

每个进程将其环境存储在 /proc/$PID/environ 文件中。此文件包含每个键值对,并用空字符 (\x0) 分隔。可以使用 sed 获得更易于人类阅读的格式,例如 sed 's:\x0:\n:g' /proc/$PID/environ

定义变量

为了避免不必要地污染环境,您应该设法限制变量的范围。实际上,图形会话和 systemd 服务要求您在特定位置设置变量才能生效。环境变量的作用域分为它们影响的上下文

全局地

使用 shell 初始化文件

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

以下文件可用于在您的系统上定义全局环境变量,每个文件都有不同的限制

  • /etc/environmentpam_env 模块 使用,并且与 shell 无关,因此无法使用脚本或 glob 扩展。该文件仅接受 variable=value 对。
  • /etc/profile 仅为登录 shell 初始化变量。但是,它会运行脚本(例如 /etc/profile.d/ 中的脚本),并且可以被所有与 Bourne shell 兼容的 shell 使用。
  • Shell 特定配置文件 - 您的 shell 的全局配置文件,初始化变量并运行脚本。例如 Bash#配置文件(例如 ~/.bashrc)或 Zsh#启动/关闭文件(例如 ~/.zshrc)。

在此示例中,我们将创建一个函数,以将多个目录(例如 ~/bin~/scripts)添加到相应用户的 PATH 中。为此,只需将其放在您首选的全局环境变量配置文件中(/etc/profile/etc/bash.bashrc

set_path(){

    # Check if user id is 1000 or higher
    [ "$(id -u)" -ge 1000 ] || return

    for i in "$@";
    do
        # Check if the directory exists
        [ -d "$i" ] || continue

        # Check if it is not already in your $PATH.
        echo "$PATH" | grep -Eq "(^|:)$i(:|$)" && continue

        # Then append it to $PATH and export it
        export PATH="${PATH}:$i"
    done
}

set_path ~/bin ~/scripts

在不同 shell 之间共享环境变量的一种方法是创建一个没有任何注释、空行或空格 (bash) 的文件,该文件可以直接被 envsubst 读取(灵感来自 [1]

.env
EDITOR=vim
XDG_CACHE_HOME=$HOME/.cache
XDG_CONFIG_HOME=$HOME/.config
XDG_DATA_HOME=$HOME/.local/share
XDG_STATE_HOME=$HOME/.local/state
~/.bashrc
export $(envsubst < .env)
~/.config/fish/config.fish
export (envsubst < .env)

使用 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} 未链接到 HOMESHELL 环境变量,它们默认未设置。

该格式还允许使用 ${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

注意: dbus 守护程序和 systemd 的用户实例不会继承在 ~/.bashrc 等位置设置的任何环境变量。这意味着,例如,像 GNOME Files 这样的 dbus 激活程序默认情况下不会使用它们。请参见 systemd/User#环境变量
提示: 您可以发出 export -p 来查看为用户会话声明的全局和本地环境变量。

图形环境

如果环境变量仅影响图形应用程序,您可能希望通过仅在图形会话中设置它来限制其作用域。按作用域递减顺序排列

按桌面环境会话

某些图形环境(例如 KDE Plasma)支持在登录时执行 shell 脚本:它们可用于设置环境变量。例如,请参见 KDE#自动启动

按Xorg会话

修改 Xorg 会话环境的过程取决于它的启动方式

尽管脚本的结尾取决于它是哪个文件,并且任何高级语法都取决于使用的 shell,但基本用法是通用的

~/.xprofile, ~/.xinitrc, or ~/.xsession
...
export GUI_VAR=value
...
按Wayland会话

由于 Wayland 不会初始化任何与 Xorg 相关的文件,因此 GDMKDE Plasma 转而 source systemd 用户环境变量。

~/.config/environment.d/envvars.conf
GUI_VAR=value

尚无其他支持 Wayland 会话的显示管理器(例如 SDDM)为此提供直接支持。但是,LightDMSDDM 也为 Wayland 会话上的登录 shell source 启动脚本。

greetd 也 source /etc/profile~/.profile - 此行为由其 source_profile 设置控制,默认情况下启用。

如果您的显示管理器 source 启动脚本(如 ~/.bash_profile)并且您想使用 environment.d,则可以按如下方式 source 它

~/.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 默认导出(至少在 Bash 中是这样;请参见 declare -p | grep PATH),因此 PATH=...export PATH=... 的作用相同;最好对其中一个示例使用另一个变量。(在 Talk:Environment variables 中讨论)

有时只需要临时变量。可能有人希望临时从创建的特定目录运行可执行文件,而无需键入每个文件的绝对路径,或者在简短的临时 shell 脚本中使用该路径。

例如,您可以在当前 shell 中定义 PATH 变量,或者使用 export 命令为所有 shell 定义它,直到您注销会话。要将特定于会话的目录添加到 PATH,请发出

$ export PATH="${PATH}:/home/my_user/tmp/usr/bin"

要仅将特定于 shell 的目录添加到 PATH,请发出

$ PATH="${PATH}:/home/my_user/tmp/usr/bin"

示例

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

  • XDG_CURRENT_DESKTOP 是一个 freedesktop.org 变量,包含一个由冒号分隔的字符串列表,用于标识当前桌面环境 [4]。 积极开发的标准化环境值包括 GNOME, GNOME-Flashback, KDE, LXDE, LXQt, MATE, TDE, Unity, XFCE, EDE, Cinnamon, Pantheon, 和 DDE [5]
    • Cinnamon 的注册时间比其他桌面环境。因此,一些软件可能仍然期望其预注册值 X-CINNAMON,例如 Qt[6]
    • Hyprland 被非正式地识别为 Hyprland 的值。
  • DE 是一个遗留变量,指示正在使用的desktop environment(桌面环境)。 没有关于可能值的中心文档,但 xdg-utils 为许多桌面环境提供了参考。
  • DESKTOP_SESSION 是另一个遗留变量,类似于 DE 但不太常见。 它可能是会话的桌面条目的路径,位于 /usr/share/xsessions/[7]
  • WINDOW_MANAGER 是一个有时用于选择在桌面环境中使用的窗口管理器的变量,与此处列出的其他变量相反,后者由已选择的显示管理器或桌面环境设置,供其他程序读取。
  • PATH 包含一个由冒号分隔的目录列表,您的系统在其中查找可执行文件。 当 shell(例如 bashzsh)解释常规命令(例如 lssystemctlpacman)时,shell 会在列出的目录中查找与您的命令同名的可执行文件,并执行它。 要运行未在 PATH 中列出的可执行文件,必须给出可执行文件的相对或绝对路径,例如 ./a.out/bin/ls
注意: 出于安全原因,建议不要将当前工作目录 (.) 包含到您的 PATH 中,因为它可能会诱骗用户执行恶意命令。
  • HOME 包含当前用户主目录的路径。 应用程序可以使用此变量将配置文件等与运行它的用户关联起来。
  • OLDPWD 包含上一个工作目录的路径,即上次执行 cd 之前 PWD 的值。
  • TERM 包含正在运行的终端的类型,例如 xterm-256color。 终端中运行的希望使用终端特定功能的程序会使用它。
  • MAIL 包含传入电子邮件的位置。 传统设置是 /var/spool/mail/$LOGNAME
  • ftp_proxyhttp_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 is much better than us at figuring this out”(Man 比我们更擅长弄清楚这一点),因此通常应将此变量保持未设置状态。 请参阅 manpath(5)
  • INFODIR 包含一个由冒号分隔的目录列表,info 命令在其中搜索 info 页面,例如,/usr/share/info:/usr/local/share/info
  • TZ 可用于为用户设置与系统时区不同的时区。 可以使用 /usr/share/zoneinfo/ 中列出的区域作为参考,例如 TZ=":/usr/share/zoneinfo/Pacific/Fiji"。 当将 TZ 变量指向 zoneinfo 文件时,它应该以冒号开头,根据 GNU 手册

默认程序

  • SHELL 包含用户首选 shell 的路径。 请注意,这不一定是当前正在运行的 shell。 如果它没有值,Bash 将自动将此变量设置为用户在 /etc/passwd 中定义的登录 shell,如果无法确定,则设置为 /bin/sh
  • PAGER 包含运行用于列出文件内容的程序的命令,例如 /bin/less
  • EDITOR 包含运行用于编辑文件的轻量级程序的命令,例如 /usr/bin/nano。 例如,您可以编写一个在 X 下的 geditnano 之间进行交互式切换的程序,在本例中
[ -n "$DISPLAY" ] && export EDITOR=gedit || export EDITOR=nano
  • VISUAL 包含运行功能齐全的编辑器的命令,该编辑器用于更苛刻的任务,例如编辑邮件(例如,vivimemacs 等)。
  • BROWSER 包含 Web 浏览器的路径。 在交互式 shell 配置文件中设置此项很有帮助,以便可以根据图形环境的可用性动态更改它,例如 X
[ -n "$DISPLAY" ] && export BROWSER=firefox || export BROWSER=links
提示: 如果 Wayland 合成器 正在运行,这些默认程序也可以有条件地设置,方法是使用 WAYLAND_DISPLAY 环境变量。

另请参阅