问题描述
设置 PATH
envvar 的首选位置在哪里?
~/.profile
或 /etc/environment
?
两处都设置了PATH
是什么情况?最终结果是在这两个地方设置的两个值的串联吗?
最佳方案
概括:
-
如果您只想为当前用户而不是计算机的所有用户向
PATH
变量添加路径(例如/your/additional/path
),通常将其放在~/.profile
的末尾,就像这两个示例之一:PATH="/your/additional/path:$PATH" PATH="$PATH:/your/additional/path"
请注意,路径优先级从左到右递减,因此第一条路径的优先级最高。如果您将路径添加到
$PATH
的左侧,它将具有最高优先级,并且该位置中的可执行文件将覆盖所有其他路径。如果您在右侧添加您的路径,它将具有最低优先级,而来自其他位置的可执行文件将是首选。 -
但是,如果您需要为所有用户设置该环境变量,我仍然不建议触摸
/etc/environment
而是在/etc/profile.d/
中创建一个文件名以.sh
结尾的文件。/etc/profile
脚本和/etc/profile.d
中的所有脚本是每个用户个人~/.profile
的全局等效项,并且在初始化期间由所有 shell 作为常规 shell 脚本执行。
更多详情:
-
/etc/environment
是 system-wide 配置文件,表示所有用户都使用。但是它归root
所有,因此您需要成为管理员用户并使用sudo
对其进行修改。 -
~/.profile
是您自己的用户的个人 shell 初始化脚本之一。每个用户都有一个,可以在不影响其他人的情况下编辑他们的文件。 -
/etc/profile
和/etc/profile.d/*.sh
是全局初始化脚本,相当于每个用户的~/.profile
。不过,全局脚本在 user-specific 脚本之前执行;并且主/etc/profile
在退出之前执行/etc/profile.d/
中的所有*.sh
脚本。
-
/etc/environment
文件通常只包含这一行:PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
它将系统上所有用户的
PATH
变量设置为此默认值,不应以重大方式更改该值。至少你不应该从中删除任何重要的路径,比如/bin
、/sbin
、/usr/bin
和/usr/sbin
。该文件被每个用户的每个 shell 读取为第一个配置文件之一。请注意,它不是 shell 脚本。它只是一个以某种方式解析的配置文件,它可能只包含环境变量赋值!
-
~/.profile
文件可以包含很多内容,默认情况下,它包含检查~/bin
目录是否存在并将其添加到用户现有的PATH
变量中的其他内容,就像这样(在 16.04 之前的较旧 Ubuntu 版本上——它无条件地添加——在 18.04 上,它还添加了 “~/.local/bin”):# set PATH so it includes user's private bin if it exists if [ -d "$HOME/bin" ] ; then PATH="$HOME/bin:$PATH" fi
您会看到
PATH
的旧值在此处被重用,新路径仅附加到开头而不是覆盖所有内容。当您手动想要添加新路径时,您还应该始终将旧的$PATH
值保留在新字符串的某处。这个初始化脚本只能被它所属的用户的 shell 读取,但还有另一个条件:
# ~/.profile: executed by the command interpreter for login shells. # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login # exists.
因此,如果您使用默认的 Bash shell,如果您希望
~/.profile
中的更改对您的用户产生影响,则应确保您没有~/.bash_profile
或~/.bash_login
。
要全面了解环境变量,请参阅:https://help.ubuntu.com/community/EnvironmentVariables
相关问题:difference between bash.bashrc and /etc/environment file
次佳方案
This answer is mainly about the order in which environment variables like
PATH
are assigned when specified in different configuration files. I do also cover where you should usually set them, but the list below does not list files in the order that you should consider using them. For general information on settingPATH
and other environment variables in Ubuntu, I also recommend reading EnvironmentVariables and the other answers to this question.
设置 PATH
的首选位置取决于您需要为其设置的用户以及您希望设置它的时间和方式。您的决定的一部分将是您是否希望为所有用户或基于 per-user 设置环境变量。如果您不确定,那么我建议只为一个用户(例如,您的帐户)而不是系统范围设置它。
作为 AlexP says , PATH
环境变量将具有它最近分配的值。实际上,大多数情况下,您设置 PATH
时,会将 PATH
的旧值包含在新值中,以便保留以前的条目。
因此,实际上,当 PATH
从多个文件中设置时,它通常包含所有文件中给出的条目。但这只是因为设置它的所有文件(第一个除外)通常引用 PATH
变量本身,导致其旧值包含在新值中。
因此,您实际上是在询问各种文件中的 PATH
设置生效的顺序。
常见的,general-purpose 设置 PATH
的地方按照用户登录时生效的顺序列出如下,而不是你通常应该考虑使用它们的顺序。下面列出的每个位置在某些情况下都是设置 PATH
的合理选择,但大多数情况下只有少数是不错的选择。
在下面的列表中,您将看到一些目录名称,例如 ~/.profile
。如果您不熟悉 tilde expansion , ~/
是指当前用户的主目录。我主要使用这种语法来实现紧凑性。它在 shell 脚本中受支持,但在 PAM 配置文件中不受支持。
1.对于所有用户:/etc/environment
Ubuntu 上的 PAM 会导致设置 /etc/environment
中列出的环境变量,如果该文件存在,默认情况下是这样。这就是所有用户的环境变量最常见的设置方式。
$ cat /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
如果您必须为所有用户帐户设置环境变量,而不仅仅是您的用户帐户,那么修改该文件可能是您的最佳选择。我建议先备份它。备份此文件的一种方法是运行:
sudo cp /etc/environment /etc/environment.orig
.orig
扩展名不是特别需要的——您可以将备份文件命名为任何不会混淆或已被使用的名称。 (除了 .orig
, .old
, .backup
和 .bak
是常见的。)
您可以以 root 用户身份( sudoedit /etc/enviromnment
、 sudo nano -w /etc/environment
、 gksudo gedit /etc/environment
等)编辑任何其他文件的任何方式编辑此文件
/etc/environment
不支持自动包含变量的旧值。但这通常是不必要的,因为大多数情况下,您会通过编辑 /etc/environment
为所有用户设置环境变量,无论如何,您都希望它是用户登录时的初始值。然后,用户可以随心所欲地更改它。通常情况下,用户能够这样做是有好处的。
2.对于所有用户:/etc/security/pam_env.conf
PAM 从 /etc/security/pam_env.conf
读取所有用户的环境变量,使用与 per-user ~/.pam_environment
文件中使用的相同语法指定(见下文)。
当在 /etc/environment
和 /etc/security/pam_env.conf
中设置相同的环境变量时,将使用 pam_env.conf
中的值——即使该值被指定为 DEFAULT
而不是 OVERRIDE
。
但是,当您用 pam_env.conf
中的一行取代 environment
中的一行时,您可以包含被取代值的内容。有关详细信息,请参阅下面有关 .pam_environment
的部分(因为它使用相同的语法)。
通常不需要编辑 pam_env.conf
,如果你这样做,你应该非常小心,因为格式错误的行通常会阻止所有普通用户帐户登录!例如,默认 pam_env.conf
包含以下行:
#PATH DEFAULT=${HOME}/bin:/usr/local/bin:/bin\
#:/usr/bin:/usr/local/bin/X11:/usr/bin/X11
这是作为几个示例之一呈现的。它说明的一件事是如何使用 \
跨多行拆分分配。假设您只取消注释第一行,但忘记取消注释第二行:
PATH DEFAULT=${HOME}/bin:/usr/local/bin:/bin\
#:/usr/bin:/usr/local/bin/X11:/usr/bin/X11
不要这样做!
我只是偶然测试了一下,它阻止了任何用户成功登录。要修复它,我必须以恢复模式启动并将其更改回来。 (幸运的是,我在仅用于测试事物的虚拟机上执行此操作,因此没有给我带来任何麻烦。)
3.对于一个用户:用户家目录中的.pam_environment
为单个用户设置环境变量的方法之一是让该用户在其主目录中编辑(或创建).pam_environment
。此文件中设置的值取代全局 /etc/environment
文件中设置的值。
.pam_environment
不是最初创建用户帐户时复制到用户主文件夹中的文件框架的一部分。但是,如果您在主目录中创建该文件,则可以使用它来设置环境变量,例如 PATH
。与 /etc/environment
不同(但与 /etc/security/pam_env.conf
相似), per-user .pam_environment
文件确实支持将环境变量的旧值扩展为新值。然而,它们不是 shell 脚本,您必须使用特殊的语法来实现这一点,这与您在 .profile
之类的文件中使用的语法有些不同。
例如,如果您想将主目录中的 bin2
目录添加到 PATH
的末尾,则可以通过将此行添加到 .pam_environment
来实现:
PATH DEFAULT=${PATH}:/home/@{PAM_USER}/bin2
有关更多详细信息,请参阅 EnvironmentVariables 的 ~/.pam_environment
小节(上例密切改编自)、man pam_env
和 man pam_env.conf
。
尽管这曾经被吹捧为 Ubuntu 用户更改或添加环境变量的首选方式,并且仍然被认为是一个合理且可接受的选择,但您在编辑 .pam_environment
时应该小心。与对系统范围 /etc/security/pam_env.conf
的编辑(见上文)一样,用户的 .pam_environment
文件中的格式错误的行将阻止登录成功。 (我已经对此进行了测试——这次是故意的。)有关 the recommendations 如何拥有 evolved 的信息,请参阅 Gunnar Hjalmarsson 的 comments below 和 ubuntu-devel
讨论。
一般来说,这样的错误比 pam_env.conf
中的错误行要轻得多,因为它只影响一个用户。但是,对于只有一个允许登录的用户帐户的桌面 Ubuntu 系统,编辑 .pam_environment
时的此类错误与编辑 pam_env.conf
时的错误一样严重——如果您尚未登录,则不会无需在恢复模式下启动(或从实时 USB 等启动)即可修复它。
(如果您确实有其他用户帐户,那么您可以以其他用户身份登录并解决问题。即使他们不是管理员并且不能 sudo
到 root,他们仍然可以运行 su your-account
并被提示输入您的(不是他们的) ) 密码。但是,guest 帐户不能这样做,因为禁止使用 su
来冒用其他用户的身份。)
4. 对于所有用户:/etc/profile
和 /etc/profile.d/
中的文件
Bourne-compatible shell(包括 bash
,Ubuntu 中的默认用户 shell)在作为登录 shell 调用时运行 /etc/profile
中的命令。
Ubuntu 的 /etc/profile
以:
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
这会导致 /etc/profile.d/
目录中名称以 .sh
结尾的任何文件中的命令也将运行。
大多数显示管理器也会导致 /etc/profile
中的命令(以及 /etc/profile.d
中的文件)也为图形登录运行。然而,并非所有人都这样做,这是支持使用 PAM 提供的工具的重要论据(见上文)——除非永远不会有任何图形登录到该系统,例如,如果它是没有安装 GUI 的服务器。
在 /etc/profile
中设置系统范围的环境变量是传统的做法,但这通常不再是最佳选择。如果您不能在 /etc/environment
中设置环境变量,并且必须为所有用户设置它,那么在 /etc/profile.d/
中创建一个新文件可能比编辑 /etc/profile
本身更好。一个原因是,当 Ubuntu 升级时,可能会有一个新的默认 /etc/profile
文件。根据您执行升级的方式,旧文件(带有您的更改)将保留在特定的更新配置文件之前,或者系统会提示您处理这种情况。
当在 /etc/profile
和 /etc/profile.d
中的一个或多个文件中设置相同的环境变量时,最后执行哪个?这取决于 /etc/profile
中设置它们的命令是出现在 profile.d
中的文件之前还是之后(通过我上面引用的代码)。 /etc/profile
中的命令按照它们出现的顺序执行。
/etc/profile
是一个shell 脚本,它的语法与上面讨论的PAM 配置文件的语法不同。它的语法与 per-user ~/.profile
文件的语法相同(见下文)。
如果您需要编写代码来决定是否将特定目录添加到 PATH
(并为所有用户添加),您将无法使用 /etc/environment
或 /etc/security/pam_env.conf
来执行此操作。这可能是最好使用 /etc/profile
或 /etc/profile.d/
的主要情况。
5.对于一个用户:用户家目录中的.bash_profile
如果用户有 ~/.bash_profile
,bash 使用它而不是 ~/.profile
或 ~/.bash_login
(见下文)。您的主目录中通常不应有 .bash_profile
。
如果你这样做,它通常应该包含一个命令来获取 ~/.profile
(例如, . "$HOME/.profile"
)。否则,per-user .profile
文件的内容根本不会运行。
6.对于一个用户:用户家目录中的.bash_login
如果用户有 ~/.bash_login
,bash 使用它而不是 ~/.profile
(见下文),除非 ~/.bash_profile
存在,在这种情况下,除非来自`~/.bash_login,否则不会使用其他任何一个。
与 .bash_profile
一样,您的主目录中通常不应有 .bash_login
文件。
7. 对于一个用户:用户主目录中的 .profile
。
当 Bourne-style shell 作为登录 shell 运行时,它运行 /etc/profile
中的命令(通常包括导致运行 /etc/profile.d/
中文件中的命令的命令——见上文)。之后,它运行用户主目录中 .profile
中的命令。该文件对每个用户都是独立的。 (如果 .bash_profile
或 .bash_login
存在,Bash 实际上会运行它们——但是,对于 Ubuntu 系统上的用户,这些文件很少应该或确实存在。有关详细信息,请参见上文和 the Bash manual 中的 6.2 Bash Startup Files 。)
因此,~/.profile
是用户放置登录时运行的命令的主要位置。这是您设置 PATH
的传统位置,但由于 Ubuntu 具有 pam_env 模块并支持 ~/.pam_environment
,您应该考虑使用它。
与 /etc/profile
一样,并非所有显示管理器都为图形登录运行此文件,尽管大多数都这样做。这是更喜欢 ~/.pam_environment
来设置环境变量的原因(就像人们可能更喜欢 /etc/environment
而不是 /etc/profile
)。
当您在 .pam_environment
中设置 PATH
时,您可以扩展环境变量,包括 PATH
本身(见上文)。但是,如果您需要以更复杂的方式设置 PATH
,则可能必须改用 .profile
。特别是,如果您想在每次用户登录时检查目录是否存在,并且仅在存在时将其添加到 PATH
,那么您将无法使用您的 .pam_environment
文件将该目录添加到您的 PATH
。
例如,Ubuntu 上的默认 per-user .profile
文件曾经以:
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
有关详细信息,请参阅 Byte Commander’s answer 上的 Gunnar Hjalmarsson 的 comment。
这将检查您的主目录是否有 bin
子目录。如果是这样,它会将该子目录添加到 PATH
的开头。
该列表忽略了一些可能性。
当用户登录时,还有其他方式设置环境变量,这在很大程度上取决于登录类型。例如,您可能偶尔会为图形登录或仅为基于 SSH 的远程登录设置环境变量。上面的列表不包括这种情况。
我遗漏了一些人们有时会定义环境变量的文件,例如 ~/.bashrc
和 /etc/bash.bashrc
,因为通常不推荐将它们设置为 PATH
的位置,并且您实际上很少将它们用于此目的。如果您使用这些文件将目录添加到 PATH
,那么它们有时会被添加多次,并且在您检查 $PATH
时会非常混乱。 (在极端情况下,这可能会减慢速度,但通常只是保持一切干净和易于理解。)
由于 bash
是 Ubuntu 用户的默认登录 shell,并且大多数用户使用它或其他一些 POSIX-compatible shell,因此我省略了有关如何在其他非 Bourne 样式 shell 中设置环境变量的信息,例如 tcsh
。
第三种方案
/etc/environment 文件不是您不能在那里使用 export 的脚本文件,它不支持 $HOME 类型的变量扩展,只是 simplevariable=value 对。因此,要使用该文件,您只需将路径附加到现有定义中,该定义专门用于 system-wide 环境变量设置。每行一个。具体来说,此文件存储 system-wide 语言环境和路径设置。
~/.profile – 每当执行 bash shell 时都会执行此文件,通常是推荐用于环境变量的文件,但是它的缺点是只能由登录 shell 调用,因此为了使其生效,您需要注销并重新登录 – 或者至少启动一个新的登录 shell。