我的 shellzsh
和操作系统是 Ubuntu 13.04
我需要将目录添加到 $PATH 才能使其在以下位置工作:
- 在图形环境(Unity)中(例如启动应用程序、
gmrun
通过快捷方式运行的程序(基本上是 alt+f2 上的“运行命令”) - 在 Unity 终端中
- 在终端上Ctrl++AltF1
我已经添加了它.profile
,它适用于前两点,但不是最后一点。我知道我可能会添加它,.zshrc
但在这种情况下,它将被写入两个地方(违反 DRY),并且在 unity 内部终端的情况下,它将被写入两次$PATH
(我不认为这很糟糕,但至少不漂亮)
如果我仅将其添加到.zshrc
它仅适用于第二种和第三种情况(显然)
我能做些什么?
答案1
为所有登录设置环境变量(无论类型)
最好的办法是使用~/.pam_environment
。例如,/opt/blah/bin
在末尾添加PATH
,你可以把这个放在.pam_environment
你的主目录中的文件中:
PATH DEFAULT=${PATH}:/opt/blah/bin
全局设置环境变量(但除非必要,否则不要这样做)
如果你想添加一些PATH
东西全部用户,而是使用/etc/environment
。令人困惑的是,它们使用的语法并不相同。虽然它们实际上都不是脚本,但/etc/environment
看起来像脚本(~/.pam_environment
/etc/environment
没有任何export
命令)。因此,如果你想要添加/opt/blah/bin
到每个人的末尾PATH
,并且PATH
行/etc/environment
开始为
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
那么你可以将其更改为:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/blah/bin"
分析
大多数 Bourne 风格的 shell(包括)在作为登录 shell 启动时bash
都会执行 source 。是一个不寻常的例外;它仅在使用传统 Bourne 风格的 shell 之一的名称调用时才会执行此操作。也就是说,如果你~/.profile
zsh
称呼 zsh
通过名称sh
或(最常见的方法是使用其中一个名称ksh
创建符号链接来实现),它将表现得像它们和源(如果它是登录 shell)。否则,它不会。(来源:zsh
~/.profile
man zsh
。
这就是zsh
为什么虚拟控制台会话(例如,您转到Ctrl++Alt的位置F1)不会设置PATH
环境变量~/.profile
。它是一个登录 shell,但zsh
很特殊;它的行为不像传统的 Bourne 风格 shell,除非它假装是这样的。
为什么zsh
运行终端窗口时会显示你设置的环境变量~/.profile
?因为在你启动终端之前,它们已经在你的图形会话中设置好了. 当您以图形方式登录时,显示管理器(提供图形登录屏幕并管理图形会话)充当登录 shell。通常它来源~/.profile
(尽管它不是保证它会这样做,有时有人会更改桌面环境,却发现~/.profile
当他们以图形方式登录时不再有来源)。
基于文本的虚拟控制台不会~/.profile
不获取源代码。例如,如果您的 shell 是bash
而不是zsh
,并且您在虚拟控制台中登录,~/.profile
则会获取源代码。问题是,与传统 Bourne 风格 shell 的可靠行为以及显示管理器启动图形登录会话的不太可靠的行为不同,当它是您的登录 shell 时zsh
不会获取源代码~/.profile
。
类似地,在设置了环境变量的情况下~/.profile
,如果您要远程登录(例如,通过启用 SSH 并以此方式登录),~/.profile
则将无法获取来源。
/etc/profile
顺便说一句,这也适用于全局文件。如果您在那里全局设置环境变量,您将遇到与在 中为用户设置环境变量相同的行为~/.profile
。
解决方案,假设您不需要编写脚本测试来确定环境变量的内容,是在 中设置用户特定的环境变量~/.pam_environment
,并在 中设置系统范围(即所有用户)的环境变量/etc/environment
。
当你这样做的时候,聚丙烯酰胺(具体来说,pam_env.so
)为每种类型的登录设置登录变量,并这样做前登录 shell(例如,zsh
对于bash
大多数人来说)或类似登录 shell 的东西(例如,显示管理器)提供自己的登录配置文件。这是目前在 Ubuntu 上设置环境变量的一般推荐方法。
~/.profile
这种方式解决了一些登录 shell 并不总是提供和的问题/etc/profile
(这是您遇到的问题)。它还解决了显示管理器在初始化图形登录会话时偶尔不提供该文件的问题(这是您遇到的问题不是经历)。
备择方案
如果什么:
- 您需要根据脚本测试的结果在登录时设置环境变量吗?或者
- 您只是不想使用
.pam_environment
(或者对于系统范围的变量,/etc/environment
?
如果您没有使用zsh
,而是使用了bash
或其他更传统的 Bourne 风格 shell,那么您只需在 中设置环境变量~/.profile
(或/etc/profile
设置系统范围的变量)。有时,在配置中,这不会为图形登录会话设置它们,但通常它可以工作。
将它们设置~/.bashrc
不适用于此目的。本质上仅bash
提供该文件,因此当zsh
您的登录 shell 或显示管理器充当您的登录 shell 时,它都不会起作用。(换句话说,在您的情形下,它根本无法工作。)
因此,如果您需要一个适用于所有类型的登录且~/.profile
适用于图形会话的脚本,您可以简单地:
- 修改
zsh
源的配置~/.profile
,或者 - 制作两个
zsh
的配置并~/.profile
获取第三个共享文件。(这甚至可以添加到图形会话的单独配置文件中,例如.xsession
,如果以后有需要的话。)
and made sure they--and the contents of any script sourced from
在这两个选项中,除非您已经阅读过 ~/.profile .profile zsh`的内容,否则第二个选项更好--won't cause problems if sourced by
。(通常不应该,但你永远不知道。)
在登录时修改、制作zsh
源~/.profile
(或其他脚本)的最佳配置文件是~/.zprofile
。这对应于~/.profile
更传统的 Bourne 风格 shell。(严格来说,它是$ZDOTDIR/.zprofile
,但$ZDOTDIR
通常是~
。)
您需要将该行添加source $HOME/.profile
到该文件中。
不过,我强调一下,如果只需要对环境变量执行简单的赋值(包括递归赋值,其中环境变量被分配一个包含其自身和/或其他环境变量的表达式),你应该使用~/.pam_environment
如上所述(或/etc/environment
针对系统范围的环境变量)。
答案2
首先,您只需在 .zshrc 文件中获取 .profile 即可。
除此之外,当您使用 zsh 时,您可以将以下内容添加到 .zshrc 中:
typeset -U path
# If you want it at the front of your path
path=({/custom/path/bin "${path[@]}")
# If you want it at the end of your path
path+=(/custom/path/bin)
工作原理:
在 zsh 中,$PATH
变量绑定到$path
变量;$path
是一个数组,并且$PATH
是一个标量,其中的元素$path
由 连接:
(与 相同${(j|:|)path}
)。typeset -U path
使得数组的元素path
(以及$PATH
)是唯一的。
typeset [ {+|-}AEFHUafghklprtuxmz ] [ -LRZi [ n ]] [ name[=value] ... ]
typeset -T [ {+|-}Urux ] [ -LRZ [ n ]] SCALAR[=value] array [ sep ]
Set or display attributes and values for shell parameters.
(...)
-U For arrays (but not for associative arrays), keep only
the first occurrence of each duplicated value. This may
also be set for colon-separated special parameters like
PATH or FIGNORE, etc. This flag has a different meaning
when used with -f; see below.
答案3
这个答案基本上基于 Eliah Kagan 的答案,包含了我真正做的事情。
我已经添加到~/.pam_environment
PATH DEFAULT=${PATH}:/home/riad/scripts
但至少在我的 PC 上,它不是在 tty1 (++) 登录时解析的,Ctrl而是在图形登录时解析的。(即使是由 unity 创建的语言环境设置在非图形登录中也不起作用)AltF1
原因是 lightdm 的 pam 配置文件中有以下行(/etc/pam.d/lightdm
):
session required pam_env.so readenv=1 user_readenv=1 envfile=/etc/default/locale
我在/etc/pam.d/login
之间添加了相同的行
@include common-session
和
@include common-password