I had previously submitted a file for use as `/etc/zsh/zshenv' which has gone into use. While it is functional and was certainly an improvement over the pre-existing setup, I no longer believe it was entirely the correct solution. Having consulted the Zsh documentation regarding its start up files and compared that with that of other shells, I think that `/etc/zsh/zprofile' is the proper file to be used for what is now being done in `/etc/zsh/zshenv'. Therefore, I think that `/etc/zsh/zshenv' should be removed and replaced by `/etc/zsh/zprofile'. I will be creating an attachment for use as `/etc/zsh/zprofile'
Created attachment 11119 [details] /etc/zsh/zprofile This is very similar to my old `/etc/zsh/zshenv'. A notable tweak is removing the unnecessary `/usr/bin/whoami' command substitution and replacing it with the Zsh `USER' environment variable. This is, at least, a bit more efficient by removing the execution of an external command.
Yes, I agree. The zshenv file got sourced in inappropriate times (i.e. at every shell invocation). For instance, if I ran less, it invoked zsh to run lesspipe.sh, and zshenv gets sourced (which is not desired). The only sticky problem is how to handle the old zshenv file when installing the new zprofile file. I submitted a potential solution in my zsh 4.1.1 ebuild that renames the user's zshenv file to zprofile (if they don't have a zprofile file already) during the pkg_preinst step, and then our install of the zprofile file will handle any user changes during the etc-update step. See bug 23114 for my 4.1.1 ebuild.
So long, and thanks for all the fish
Thank you for your contribution. Both of your comments helped me a lot. /etc/zsh/zprofile is included in zsh-4.0.7.ebuild in CVS now.
Hm. I just found this bug, and I'm not sure that this is the right thing. I agree that zshenv isn't the right file for this, but zprofile is sourced only at the startup of a login shell. Which means that other interactive, but not login, shells won't source this file. This is different from bash, whose man page says that /etc/profile is sourced for all interactive shells or noninteractive login shells, but the same as ksh, which says its sources /etc/profile only on login. So obviously there's room for interpretation. Just something to think about.
My understanding of what Bash's man page states is that `/etc/profile' is read by Bash only when it is a login shell (interactive and non-interactive). Quoting Bash's man page, fourth paragraph from the section "INVOCATION": "When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. ..."
You can check the behaviour of interactive and login shell: zsh: rico% export PATH=/bin:/usr/bin rico% (zsh -c printenv | grep '^PATH') PATH=/bin:/usr/bin rico% (zsh -i -c printenv | grep '^PATH') PATH=/bin:/usr/bin rico% (zsh -l -c printenv | grep '^PATH') PATH=/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-gentoo-linux/gcc-bin/3.2:/opt/Acrobat5:/usr/X11R6/bin:/opt/blackdown-jre-1.4.1/bin:/usr/qt/3/bin:/usr/kde/3.1/bin:/usr/qt/2/bin rico% (zsh -l -i -c printenv | grep '^PATH') PATH=/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-gentoo-linux/gcc-bin/3.2:/opt/Acrobat5:/usr/X11R6/bin:/opt/blackdown-jre-1.4.1/bin:/usr/qt/3/bin:/usr/kde/3.1/bin:/usr/qt/2/bin bash: bash-2.05b$ export PATH=/bin:/usr/bin bash-2.05b$ (bash -c printenv | grep '^PATH') PATH=/bin:/usr/bin bash-2.05b$ (bash -i -c printenv | grep '^PATH') PATH=/bin:/usr/bin bash-2.05b$ (bash -l -c printenv | grep '^PATH') PATH=/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-gentoo-linux/gcc-bin/3.2:/opt/Acrobat5:/usr/X11R6/bin:/opt/blackdown-jre-1.4.1/bin:/usr/qt/3/bin:/usr/kde/3.1/bin:/usr/qt/2/bin bash-2.05b$ (bash -l -i -c printenv | grep '^PATH') PATH=/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-gentoo-linux/gcc-bin/3.2:/opt/Acrobat5:/usr/X11R6/bin:/opt/blackdown-jre-1.4.1/bin:/usr/qt/3/bin:/usr/kde/3.1/bin:/usr/qt/2/bin From the manpage as James suggested, I think this is the right behaviour and not a bug.
reopen requested
The problem with this solution is that it may stomp over a user's .zshenv file if that's where they modify their own private PATH. The same goes for anything in set by /etc/profile.env which the user tries to set. AFAIK all environment settings should go in /etc/zsh/zshenv. This always gets sourced, sure, but it's possible to detect if you're a login and/or interactive shell and skip most of the parsing if that's the case. The INTERACTIVE and LOGIN options are the appopriate things to test for, I hope. If I get a chance later this weekend I'll try to come up with a suitable set of replacement /etc/zsh/* files. Cheers, - Andrew
Created attachment 17161 [details] zshenv
Hi. I was asked about the same issue two or three weeks ago at local forum but he didn't reopen this bug .... I understand it is a bit annoying if you use ~/.zshenv to set PATH enviroment. I attached a zshenv file to parse /etc/profile.env if [[ ${SHLVL} = 1 ]]. It may be [[ -o LOGIN ]] (if you prefer zsh options). Which do you think is better?
Personally, as a matter of style I think [[ -o LOGIN ]] is preferable since it's obvious what it's doing; the SHLVL==1 thing may be functionally equivalent but it's less clear what it's doing at a glance. Thanks for the prompt response, - Andrew
The problem here is that there is confusion about what .zshenv should be used for. The statment that all environment variables should go into a zshenv file (either personal or system) is incorrect. The *env files are simply sourced for all invocations of the shell, and should only be used to make modifications that need to affect every shell invocation. Many people think that they need to set their PATH in the .zshenv file, and then they get royally screwed if they do something like this: PATH=/testing/path:/usr/bin gdb test-program This completely ignores the custom PATH if their .zshenv file sets the PATH (this is because gdb runs the program using $SHELL). So, for most people, they need to move things out of their .zshenv file into their .zprofile file. In certain older X Windows environments, the .zprofile file did not get sourced, but that can be checked for and sourced in the users .zshrc file (or they can upgrade their X Windows version).
Wayne: Your example seems fair enough, and I admit I'd never thought of that (or been royally screwed in the manner you suggest). I was also under the impression that all environment settings go in *env, possibly due to its name. Speaking to a few friends who use zsh, it appears to be a fairly common perception. Reading the man page actually doesn't offer advice of what goes where; it only describes the behaviour. The FAQ question "3.2: In which startup file do I put...?" (<http://zsh.sunsite.dk/FAQ/zshfaq03.html#l18>) offers a bit more guidance, and indeed does advise that *login and *shrc are "are a good place to set environment variables (i.e. export commands), since they are passed on to all shells without you having to set them again". So I guess the initial closure for this bug was indeed correct and I should fix my personal startup files. :) - Andrew
quote=Wayne Davison: "The problem here is that there is confusion about what .zshenv should be used for .." /etc/zsh/zshenv *is* the place for $path and .zshenv *should* be considerd the place to change this env. Look at StartupFiles/zshenv and you will see that this is what zshenv is intended for, and .zshenv should be respected as "the place" for a user to change this. Go to zsh.org and look at the .zshenv under startup files and you will see that $path is defined here .. it's standard and accepted practice. In my own case $path is pretty much all I define in .zshenv, and it's a fairly sure bet I will want this defined for each and every invocation .. as of the 4.0.7 update I *can't* define it here as it gets redefined in /etc/zsh/zprofile. " .. for most people, they need to move things out of their .zshenv file into their .zprofile file" No .. the package maintainer should follow the practices layed out by the zsh developers and have $path in /etc/zsh/zshenv. Additionally /etc/profile.env should not be sourced but env-update should be addapted to also support zsh. "PATH=/testing/path:/usr/bin gdb test-program" How may people do you think would really do this???!! As for defining $path it can be done in a simple array: # .zshenv # PATH typeset -U path export path path=($path ~/bin /path/bin)
"Look at StartupFiles/zshenv ..." Yes, I'm about to commit a patch to zsh to fix this comment, so it won't be there to mislead people much longer (yes, I'm one of the developers working on zsh). I too used to have many of my environment variables set in the .zshenv file, and I very nearly corrupted a production system at work a few years ago because of this. So, we need to be sure that environment customizations aren't lost at every shell invocation. The gdb example was just one such command that can bite people, and simply should have made it clear that improper use of the .zshenv file can bite you unexpectedly. There are lots more potential pitfalls (basically anything that uses $SHELL). So, having the system set PATH once in /etc/zprofile is the right place for it to happen. If you want to have your .zshenv file override a setting from /etc/zprofile, you can either link your .zshenv to your .zprofile file, as Bart suggests here: http://www.zsh.org/mla/users/1997/msg00575.html Or, source it from that file (if you have other things in your .zprofile).
Here is a ZSH $PROMPT which looks identical to the default Gentoo BASH-prompt, both for root and for users: PROMPT=$'%{\e[1;3%(!.1.2)m%}%n@%m %{\e[34m%}%1d %(!.#.$) %{\e[0m%}' Please include it in the default zprofile. If you want it distinguishable (is that a word?:) from BASH here is the prompt I use personally. It's almost identical to the Gentoo BASH-default but it uses ~ for $HOME and % instead of $ for users. PROMPT=$'%{\e[1;3%(!.1.2)m%}%n@%m %{\e[34m%}%1~ %# %{\e[0m%}'
I personally do not want to enable such a prompt by default. I committed Gentoo prompt like yours yesterday, bug #43753, but only added einfo to let users do the job by themselves. I like the idea of distinguising zsh prompt from bash prompt, so I'll change $ to % and home directory to ~ in the next prerelease. If there are a number of people who want to enable it by default, I'll do so, but I'll add ``vanilla'' local IUSE flag for users who don't want it. What do you think about it?
If I add ~/bin to PATH in my .zshenv, then it's clobbered by /etc/zsh/zprofile. If I move that to my .zshrc or .zprofile, then it doesn't get sourced when I ssh into the machine to run a program, like "ssh machine program". In that case "program" isn't searched in ~/bin. If I link .zprofile to .zshenv or source .zshenv from .zprofile, then .zshenv will get sourced twice for login shells (not the end of the world, but lame). For those of you who were advocating moving PATH out of .zshenv, how do you handle the "ssh" problem? (The "ssh" problem came up because subversion in ssh mode tries to run "svnserve" and it must be in your path.) Perhaps a solution is to have /etc/zsh/zprofile save the PATH on invocation, source /etc/profile.env, then merge the two paths afterwards.
Created attachment 29430 [details, diff] sample zprofile to preserve users' path So probablly it's better to add a patch like this? It only preserve users' PATH (scripts in /etc/env.d set many other environment variables but you cannot stop them clearing your settings in ~/.zshenv if we stick to use /etc/zsh/zprofile).
Mamoru: Your patch works for me, but like you said it only saves PATH, not MANPATH, CLASSPATH, etc. So I'm going to keep linking $HOME/.zprofile to $HOME/.zshenv for safety, even though it's slightly wasteful. It really does seem like zsh's default behavior is wrong, and it should always source the system files first, letting the user override using local files. I suppose another option is to have /etc/profile.env check each variable before setting it. Path variables would be appended and non-path variables (e.g., LESS and CC) would be left alone if they were already set. Yuk.
*** Bug 102189 has been marked as a duplicate of this bug. ***
*** Bug 148196 has been marked as a duplicate of this bug. ***
This doens't really have that much in common with this bug, but apperently some dev thought it did, so I will repost what I said in the other thread. The issue with with JAVA_HOME not being set accordingly with the new java-config. The code was updated with bash profile, but not zsh, and probably other shells also, but these bug looks like it is dead, and being ignored, so nothing will porbably come of this. Anyhow, this is what I found. in /etc/profile, there this code for sh in /etc/profile.d/*.sh ; do if [ -r "$sh" ] ; then . "$sh" fi done unset sh /etc/zsh/zprofile does not have this. Thereforce my java vm was being set by the old way in env.d directory. This was preventing me from using java 1.5. I check the zprofile in the zsh files dir, and this code is not in there. I think it might need to be added, I read through the docs and didn't see anything about messing with the shell's profile.T
sys-apps/qingy is affected by this bug, too. If zsh does not have the system PATHs set in /etc/zsh/zprofile, qingy is not able to fire up X sessions because xinit can't find the X server in PATH.
Sorry for the delay. Changed zprofile to source /etc/profile.d/*.sh as suggested in comment #24.
no problem ... also note that you now have to extract the value of EDITOR in zprofile also. Here is the code I use ... stolen from /etc/profile/ # Extract the value of EDITOR [ -z "$EDITOR" ] && EDITOR="`. /etc/rc.conf 2>/dev/null; echo $EDITOR`" [ -z "$EDITOR" ] && EDITOR="/bin/nano" export EDITOR As for the profile.d/*.sh, this is now how they do it, not sure if it really matters for sh in /etc/profile.d/*.sh ; do [ -r "$sh" ] && . "$sh" done unset sh Thanks for adding this , it will make new commers to zsh life a bit easier
Sure, it is reported on bug #165000 and fixed in CVS. Thanks anyway for the information, Ryan :-)
(In reply to comment #26) > Sorry for the delay. Changed zprofile to source /etc/profile.d/*.sh as > suggested in comment #24. > A note, this will cause a warning if the directory does not contain any .sh /etc/zsh/zprofile:34: no matches found: /etc/profile.d/*.sh I made an empty .sh (dummy.sh :) to make zsh not complain when logging in.
*** Bug 207037 has been marked as a duplicate of this bug. ***
*** Bug 348622 has been marked as a duplicate of this bug. ***
*** Bug 363133 has been marked as a duplicate of this bug. ***
If you've found this bug, you might be interested in mv /etc/zsh/zprofile /etc/zsh/zshenv This works ith the current stable app-shells/zsh-4.3.11-r1
Why is this marked "RESOLVED FIXED"? For anyone starting with a fresh Gentoo install, they will get a real puzzle if they're coming from a system without a $PATHological reset in between ~/.zshenv and ~/.zshrc The sudo mv /etc/zsh/{zprofile,zshenv} fix works. Why is it not in the standard package? Thanks!
(In reply to comment #34) > Why is this marked "RESOLVED FIXED"? Let's re-open and assign to current maintainers. > ... $PATHological ... nice. > The sudo mv /etc/zsh/{zprofile,zshenv} fix works. Why is it not in the > standard package? @maintainers, can you fix this, please? For now, I've an hook in /etc/portage/env/<category>/<package> [1] x ~ # cat /etc/portage/env/app-shells/zsh pkg_preinst() { mv -v "${D}"/etc/zsh/{zprofile,zshenv} || die } [1] http://devmanual.gentoo.org/ebuild-writing/functions/pkg_preinst/index.html
Michael Weber: Cool workaround. I didn't know about those hooks. Thanks. Now let's hope the maintainers are around to fix it for real.
No love from the maintainers?
Ping.
Fixed in 5.0.2-r2.
I'm re-opening this because having this installed as /etc/zsh/zshenv is clobbering my PATH setting from ~/.zprofile. These environment variables should be set once, at login, not for every shell invocation.
(In reply to Mike Gilbert from comment #40) Scratch that; my old (modified) copy of /etc/zsh/zprofile was clobbering my settings after I moved PATH to .zshenv. That was quite confusing. I would suggest adding a warning to pkg_postrm if /etc/zsh/zprofile exists, as may happen due to config-protection.
pkg_postint I mean.
+1 Its been breaking my $PATH every time script with zsh shebang is running.
as /etc/zsh/zshenv is executed EVERY SINGLE time zsh is executed, it SHOULD NOT touch $PATH or any other variable. PATH variable should be set at zprofile, as thats what is done on login shell. All non-login shells does inherit variables from parent. This 'bugfix' acctualy broken my system.
Use case & proof of concept: I have .zshrc that setup a log of variables, including PATH. When script is executed it does not run zshrc or zprofile, which is all right, but it does run zshenv, after you put PATH settings and /etc/profile.d/* into zshenv, it does replace all my variables with default one. Its so wrong and evil that I can't believe it was commited to tree. profile.d alone is meant to be executed on login, only login, not every single zsh spawn (script, another terminal in X/tmux/screen/whatever).
(In reply to Piotr Karbowski from comment #45) > Use case & proof of concept: > > I have .zshrc that setup a log of variables, including PATH. When script is > executed it does not run zshrc or zprofile, which is all right, but it does > run zshenv, after you put PATH settings and /etc/profile.d/* into zshenv, it > does replace all my variables with default one. Its so wrong and evil that I > can't believe it was commited to tree. profile.d alone is meant to be > executed on login, only login, not every single zsh spawn (script, another > terminal in X/tmux/screen/whatever). We can either use a variable as a flag in the system's zshenv and only source the file if the variable is unset or revert to using a system zprofile and tell users they should be using .zprofile instead of .zshenv to override PATH, etc. Personally I'm fine with a flag variable, any other ideas/opinions? The following is an example of what could be prepended to the system zshenv: # Only source this the first time the shell is started to avoid overriding # customized environments. if [ -n "$ZSHGENTOO" ] ; then return fi export ZSHGENTOO=1
Well, Whatsoever we should not provide zshenv, but zprofile. This whole bugreport, as a feature enhance is wrong, zprofile shoudn't be ever changed into zshenv, all export should be done in zprofile, zshenv have so minimal usecase (a file that is executed with every zsh instance, interactive and non-interactive, including scripts) that it shoudn't be imo ever shipped with ebuild. Example of valid usecase for zshenv would be, for example, turning on ksh mode, global, so you could run ksh scripts with zsh shebang without any edition. Thats a borderline usecase, but still valid. Keeping it short, in my very opinion: 1. ebuild should provide zprofile and never zshenv. 2. user's config should be in .zshrc, which is inserted into interactive shell. adding the kind of export you proposed is really wrong, as it would emulate zprofile (run it only once, on login), but there is no reason to do so, you can just leave it as zprofile. The feedback I got from zsh side clearly say that zshenv is WRONG place to set PATH.
(In reply to Piotr Karbowski from comment #47) > Well, Whatsoever we should not provide zshenv, but zprofile. This whole > bugreport, as a feature enhance is wrong, zprofile shoudn't be ever changed > into zshenv, all export should be done in zprofile, zshenv have so minimal > usecase (a file that is executed with every zsh instance, interactive and > non-interactive, including scripts) that it shoudn't be imo ever shipped > with ebuild. ... Right, this is upstream's standard documented method which I agree we should try to adhere to. Probably the best thing would be to revert to using a system zprofile and add an elog pointing to the zshenv example installed into docs that mentions setting path and/or output other information so people quit reopening this bug. :P
+1 for revert into old zprofile thingy. shipping examples in /usr/share is of course good idea, as it can be dropped into user home and is not destructive to have it there. ;-)
(In reply to Tim Harder from comment #48) > Probably the best thing would be to revert to using a > system zprofile and add an elog pointing to the zshenv example installed > into docs that mentions setting path and/or output other information so > people quit reopening this bug. :P This has been done in zsh-5.0.2-r3; however, the elog message is only shown for new installs. I'll paste the information here so people hopefully quit opening this bug when they try to set PATH in ~/.zshenv and find it gets overridden. New info outputted by the ebuild: Note that a system zprofile startup file is installed. This will override PATH and possibly other variables that a user may set in ~/.zshenv. Custom PATH settings and similar overridden variables can be moved to ~/.zprofile or other user startup files that are sourced after the system zprofile. If PATH must be set in ~/.zshenv to affect things like non-login ssh shells, one method is to use a separate path-setting file that is conditionally sourced in ~/.zshenv and also sourced from ~/.zprofile. For more information, see the zshenv example in ${EROOT}/usr/share/doc/${PF}/StartupFiles/.