Bug 430665
Summary: | zsh should emulate sh when sourcing /etc/profile.d scripts | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | Mikel Ward <mikel> | ||||||
Component: | zsh | Assignee: | James Antill <james.antill> | ||||||
Status: | CLOSED WONTFIX | QA Contact: | Fedora Extras Quality Assurance <extras-qa> | ||||||
Severity: | low | Docs Contact: | |||||||
Priority: | low | ||||||||
Version: | 9 | CC: | dqarras, fedora | ||||||
Target Milestone: | --- | Keywords: | Reopened | ||||||
Target Release: | --- | ||||||||
Hardware: | All | ||||||||
OS: | Linux | ||||||||
URL: | http://zsh.sunsite.dk/FAQ/zshfaq02.html | ||||||||
Whiteboard: | |||||||||
Fixed In Version: | Doc Type: | Bug Fix | |||||||
Doc Text: | Story Points: | --- | |||||||
Clone Of: | Environment: | ||||||||
Last Closed: | 2009-07-15 08:23:54 UTC | Type: | --- | ||||||
Regression: | --- | Mount Type: | --- | ||||||
Documentation: | --- | CRM: | |||||||
Verified Versions: | Category: | --- | |||||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||
Cloudforms Team: | --- | Target Upstream Version: | |||||||
Embargoed: | |||||||||
Attachments: |
|
It turns out the (#qN) doesn't work if you don't have EXTENDED_GLOB set, in which case it should just be (N). I'll see if I can find a better solution. The way I chose is to put the command "emulate -L ksh" before sourcing /etc/profile.d/*.sh. This is probably a good idea anyway, since stuff in /etc/profile.d is designed for bash, not zsh, and this will turn off any incompatible options and make zsh behave more like standard sh/ksh/bash. Note that it should be done inside its own block, so that the emulation only applies for sourcing those scripts. The final code looks like: { emulate -L ksh if [ "x$SHLVL" != "x1" ]; then # We're not a login shell for i in /etc/profile.d/*.sh; do if [ -r "$i" ]; then . $i fi done unset i fi } See the URL for the long explanation of differences between zsh and sh (and zsh and bash), and how the emulate command works. I've been using emulate -L ksh for a couple of years in my .zshenv when sourcing .shrc in my home directory, and it works quite well. > /etc/zshrc assumes that the NOMATCH shell option is unset. > If it is (e.g. in ~/.zshenv) and there are no files in /etc/profile.d, the > following error is printed. But ~/.zshrc is sourced _after_ /etc/zshrc ... what is your actual problem? Wait, are you are putting interactive commands in ~/.zprofile? ... if so don't do that. The order is /etc/zshenv, ~/.zshenv, /etc/zprofile, ~/.zprofile, /etc/zshrc, ~/.zshrc, /etc/zlogin, ~/.zlogin. You can verify this in the zsh man page. My ~/.zshenv sets all my options that I want to use everywhere (scripts, console, etc.). My ~/.zprofile sets stuff that I only want to run at login time, such as running my ssh agent and setting up a script to run at logout time. My ~/.zshrc sets up my interactive settings, such as aliases and prompt. There is nothing wrong with this set up. The problem is that /etc/zshrc assumes certain conditions that may not be true. It can be fixed by running /etc/profile.d/*.sh in sh compatibility mode, which is a good idea anyway, since those scripts were written for bash not zsh. Well I would classify the NOMATCH option as an interactive thing, but I'll do the above fix for rawhide/Fedora 9. You're right, it's probably not very common, but it's very handy to be able to have exactly the same environment for scripts as at the console. It means I can be sure something I run from the console works the same when I put it in a script and run it from cron or wherever. I should note that the NOMATCH option is in fact the default in zsh, it's just you won't see this behavior unless your /etc/profile.d contains no scripts. Also, this fix should fix a whole class of other problems that could occur in scripts under /etc/profile.d, including wildcard matching ("globbing"), arrays, and word splitting, as the URL explains. Thanks very much for looking at it. Sorry, the fix I suggested only works if it's a separate function (which limits the scope of the sh emulate to that function, and reverts to the standard/user zsh options after the function exits). It should be something like: _source_profile.d() { emulate -L ksh ... } _source_profile.d This should be used in /etc/zprofile and /etc/zshrc, seeing as the/etc/profile.d/*.sh scripts are sourced in both of those files. Ok, 4.3.4-7.fc9 should be in rawhide soon and contains the fix for both files using functions. Guys, I can't reopen this but hopefully you still get my message: This Bug 430665 is almost a word-by-word duplicate of Bug 225454 but it is not marked so. Also, the Bug 225454 includes a solution blessed in the Z shell mailing lists and it is also much more compact (I would even say more elegant, too) than the one applied to latest RPM in rawhide. Please have a look at: https://bugzilla.redhat.com/show_bug.cgi?id=225454#c6 Thanks. Your proposal is to remove /etc/zshrc. The Red Hat maintainers want this kept for weird cases such as the user invokes a different terminal type and /etc/profile.d contains something specific for that terminal. (See bug 430827 for an example.) So the only difference I can see is the Red Hat one has some ugly SHLVL tests, but they're there for a reason. Also note that this close to Fedora 9 there's roughly 0% chance of changing zsh unless there's a significant bug. Post Fedora 9 we can look at using "sh" emulation instead of "ksh", if that is better for some cases. Thanks for your replies. I've been waiting for a long to get these fixed so I'm more than happy if we can get back to this after F9 is out. *** Bug 225454 has been marked as a duplicate of this bug. *** This fix has broken reading of my user .zshrc. For some reason after /etc/zshrc has finished zsh no longer reads my .zshrc file. I reverted just this change out of /etc/{zprofile,zshrc} and everything started working normally again. Here is the last few lines of zsh -lx with current rawhide: : /etc/zprofile:22 00:23:38 {$SECONDS} ; unset -f _src_etc_profile : /etc/zshrc:11 00:23:38 {$SECONDS} ; PROMPT='[%n@%m]%~%# ' : /etc/zshrc:16 00:23:38 {$SECONDS} ; bindkey ' ' magic-space : /etc/zshrc:35 00:23:38 {$SECONDS} ; _src_etc_profile_d : _src_etc_profile_d:4 00:23:38 {$SECONDS} ; emulate -L ksh : _src_etc_profile_d:8 00:23:38 {$SECONDS} ; [[ ! -o login ]] : /etc/zshrc:37 00:23:38 {$SECONDS} ; unset -f _src_etc_profile_d As you can see, /etc/zshrc has finished but .zshrc has not been executed. With this change reverted those few lines of zsh -lx become: : /etc/zshrc:11 00:35:11 {$SECONDS} ; PROMPT='[%n@%m]%~%# ' : /etc/zshrc:16 00:35:11 {$SECONDS} ; bindkey ' ' magic-space : /etc/zshrc:19 00:35:11 {$SECONDS} ; [[ ! -o login ]] : /home/martin/.zsh/.zshrc:7 00:35:11 {$SECONDS} ; ZFILE=zshrc : /home/martin/.zsh/.zshrc:8 00:35:11 {$SECONDS} ; [[ -n '' ]] : /home/martin/.zsh/.zshrc:17 00:35:11 {$SECONDS} ; _init_zshrc Note that I have ZDOTDIR set to ~/.zsh, I don't know if that is a factor in the bug. Martin, 1) can you give instructions to fully replicate your environment? 2) do you have anything special in /etc/profile.d? what if you move those files aside? 3) are all the files you source executable? are you relying on them being in PATH or do you specify the full path? 4) can you narrow down what part is causing the problem? what if you only revert zshrc? only zprofile? what if you start an interactive, non-login shell? 5) where are you setting ZDOTDIR? 6) what is the full list of files it touches before and after the change? 7) what are the differences in the output of "set" before and after the new code? 8) is it easy for you to replicate the problem without ZDOTDIR? can you produce a minimal test case? 9) is there anything else peculiar to your environment, like is the -e (exit on error) option enabled, or do you already use "emulate" in some way? A couple of other ideas: - try "unsetopt GLOBAL_RCS" in your .zshenv (to isolate that it's the /etc/ scripts causing the problem, and also as a possible workaround) - do you already set (or unset) GLOBAL_RCS or RCS at any point? - do you ever unset LOCAL_OPTIONS or do anything else that might change the behavior of functions and local variables? I've managed to reproduce this with a blank config, is is due to breakage of ZDOTDIR. % adduser zshtest % passwd zshtest % su - zshtest % echo 'export ZDOTDIR=$HOME/.zsh' > ~/.zshenv % echo "echo In .zsh/.zshrc" > ~/.zsh/.zshrc % echo "echo In .zshrc" > ~/.zshrc With the current rawhide: % zsh In .zshrc This is wrong. With the change in this bug reverted: % zsh In .zsh/.zshrc This is correct. Emptying out /etc/profile.d didn't make any difference. Sorry, don't forget -s to adduser: adduser -s /bin/zsh zshtest I don't have access to my Linux system right now. Is ZDOTDIR still set at the end of /etc/zprofile? /etc/zshrc? If not, can you figure out which line is unsetting it? Thanks for the info! Created attachment 303911 [details]
ZSH startup with bug
Created attachment 303912 [details]
ZSH startup without bug
Nothing stands out as an obvious cause.
Added some echos, ZDOTDIR is not getting unset at all, for some reason it is just being ignored. Just removing the emulate commands from inside the functions in /etc/z* is sufficient to fix it. Looks like the effect of emulate is not localised to within the function like it should be. It's actually unsetting then restoring ZDOTDIR. That is expected. I'm not sure why echo doesn't show that. $ cat .zshrc echo "In .zshrc" typeset -p ZDOTDIR typeset -p GLOBAL_RCS typeset -p RCS emulate_test() { emulate -L ksh echo "In emulate_test" typeset -p ZDOTDIR typeset -p GLOBAL_RCS typeset -p RCS } emulate_test echo "Out .zshrc" typeset -p ZDOTDIR typeset -p GLOBAL_RCS typeset -p RCS # su - zshtest In .zshrc typeset -x ZDOTDIR=/home/zshtest/.zsh typeset GLOBAL_RCS='' typeset RCS='' In emulate_test typeset ZDOTDIR='' typeset GLOBAL_RCS='' typeset RCS='' Out .zshrc typeset -x ZDOTDIR=/home/zshtest/.zsh typeset GLOBAL_RCS='' typeset RCS='' It doesn't yet explain the problem, but it's something for me to look into. Perhaps zsh does something weird if it gets set then unset. Given that the original bug has been present for a long time, and that this fix is causing regressions maybe it is worth removing the fix for the F9 release and finding a complete solution after the release has been made? So putting: # Minor bug in zsh, with regard to emulate -L see rhbz#430665 _src_noop() { emulate -L zsh } _src_noop unset -f _src_noop ...at the end of the init scripts solve the testcase, for me. It seems a little too much like magic, but putting debugging code within zsh shows that ZDOTDIR only gets reset again when the next file is sourced (i.e. emulate is implicitly called). Martin does this fix it for you? If so I'll make sure the new rcfiles are in updates-testing when Fed-9 goes GA (but probably not in updates itself for a couple of weeks after). Yes that does fix it. Changing version to '9' as part of upcoming Fedora 9 GA. More information and reason for this action is here: http://fedoraproject.org/wiki/BugZappers/HouseKeeping zsh-4.3.4-8.fc9 has been submitted as an update for Fedora 9 zsh-4.3.4-8.fc9 has been pushed to the Fedora 9 testing repository. If problems still persist, please make note of it in this bug report. If you want to test the update, you can install it with su -c 'yum --enablerepo=updates-testing update zsh'. You can provide feedback for this update here: http://admin.fedoraproject.org/updates/F9/FEDORA-2008-4099 zsh-4.3.4-8.fc9 has been pushed to the Fedora 9 stable repository. If problems still persist, please make note of it in this bug report. I was able to reproduce the emulation problem. I reported this upstream at: http://www.zsh.org/mla/users/2008/msg00781.html And, amazingly, within 24 hours on a Saturday/Sunday period a patch was posted and committed: http://www.zsh.org/mla/users/2008/msg00792.html http://zsh.cvs.sourceforge.net/zsh/zsh/ChangeLog?revision=1.4264&view=markup I think it would make sense to remove the added workaround when upgrading zsh sources to a version that includes the fix. The unneeded workaround is still present in zsh-4.3.9-4.fc11.i586. This message is a reminder that Fedora 9 is nearing its end of life. Approximately 30 (thirty) days from now Fedora will stop maintaining and issuing updates for Fedora 9. It is Fedora's policy to close all bug reports from releases that are no longer maintained. At that time this bug will be closed as WONTFIX if it remains open with a Fedora 'version' of '9'. Package Maintainer: If you wish for this bug to remain open because you plan to fix it in a currently maintained version, simply change the 'version' to a later Fedora version prior to Fedora 9's end of life. Bug Reporter: Thank you for reporting this issue and we are sorry that we may not be able to fix it before Fedora 9 is end of life. If you would still like to see this bug fixed and are able to reproduce it against a later version of Fedora please change the 'version' of this bug to the applicable version. If you are unable to change the version, please add a comment here and someone will do it for you. Although we aim to fix as many bugs as possible during every release's lifetime, sometimes those efforts are overtaken by events. Often a more recent Fedora release includes newer upstream software that fixes bugs or makes them obsolete. The process we are following is described here: http://fedoraproject.org/wiki/BugZappers/HouseKeeping Fedora 9 changed to end-of-life (EOL) status on 2009-07-10. Fedora 9 is no longer maintained, which means that it will not receive any further security or bug fix updates. As a result we are closing this bug. If you can reproduce this bug against a currently maintained version of Fedora please feel free to reopen this bug against that version. Thank you for reporting this bug and we are sorry it could not be fixed. |
/etc/zshrc assumes that the NOMATCH shell option is unset. If it is (e.g. in ~/.zshenv) and there are no files in /etc/profile.d, the following error is printed. /etc/zshrc:20: no match The best way to handle this is to add (#qN) < for i in /etc/profile.d/*.sh; do > for i in /etc/profile.d/*.sh(#qN); do