13 KiB
Configuration Files
Zsh has several system-wide and user-local configuration files.
Prezto has one user-local configuration file.
System-wide configuration files are installation-dependent but are installed in /etc by default.
User-local configuration files have the same name as their global counterparts
but are prefixed with a dot (hidden). Zsh looks for these files in the path
stored in the $ZDOTDIR
environment variable. However, if said variable is
not defined, Zsh will use the user's home directory. This is found on the
config scripts as ${ZDOTDIR:-$HOME}
and is a zsh
idiomatic way of doing
something like this:
if [[ -n $ZDOTDIR ]]; then
DOTFILES_PATH=$ZDOTDIR
else
DOTFILES_PATH=$HOME
fi
source $DOTFILES_PATH/.zshenv
#pro tip! set $ZDOTDIR on /etc/zshenv to ~/.zconf to have all runcoms live there instead of cluttering ~ =)
the above is the same as: source ${ZDOTDIR:-$HOME}/.zshenv
is equivalent to:
Sourcing of these confguration files depends mostly on 2 things:
- Whether you are running a login shell
- Whether the
RCS
andGLOBAL_RCS
options are set. They are usually set by default
File Descriptions
always runs | when GLOBAL_RCS is set |
when RCS is set |
Purpose | stuff that usually goes there, and notes |
---|---|---|---|---|
/etc/zshenv |
system provided minimal environment | Always runs! should be minimal set ZDOTDIR, minimal environment. system paths | ||
${ZDOTDIR:-$HOME}/.zshenv |
user environment overrides non-interactive, non-login shells (when invoked via shebang in a script or via zsh -c [script] or when invoked by make |
personal environment overrides, such as MANPATH , TERM , fpath non interactive scripts should have their environment completly set up here ) |
||
/etc/zshprofile |
system profile for login shells (zsh -ls zsh - or via _ssh forced command_ ) |
minimal system paths for remote interaction, site fpath , site $LOCALE , lang. |
||
${ZDOTDIR:-$HOME}/.zshprofile |
personal preferences for interactive login shells | your preferred $LOCALE , $LANG , readlne config, cdpath , session managers, additional fpath ) login shells (but non necessarily ineractive as when invoked via ssh remote cmd ) will read config up to this point |
||
/etc/zshrc |
system provided startup script, for interactive shells, (local shells that live in an XTerm , URxvt , gnome-terminal ) or subshells (like running xterm from the command prompt of a login xterm, |
site login accounting, security monitors, site command logging policy | ||
${ZDOTDIR:-$HOME}/.zshrc |
user customization of their interactive environment for terminals | sourcing custom completions (gcloud.comp.inc ), custom user frameworks (zprezto is invoked here), additional path required by custom software installed in /opt/* |
||
/etc/zshlogin |
additional customization for interactive login shells, such as those accessed via ssh | tmux attach to existing session | ||
${ZDOTDIR:-$HOME}/.zshlogin |
user script for login shell startup (this shell is a session leader, and allocates a ptty |
aliases, keybindings, personal startup programs, time tracking apps, session managers, quote of the day, fortunes | ||
.. | ... your shell session happens here ... | |||
${ZDOTDIR:-$HOME}/.zshlogout |
personal cleanup tasks | setting personal crontabs or at tasks, logging checout to your time tracking software, fortune to say goodbye. |
||
/etc/zshlogout |
site cleanup tasks | site command logging policy stop, login accounting records, security context spindown, etcThe configuration files are read in the following order: |
Discussion
There are several places to add personal configuration and preferences in
the files already provided for startup, it’s just a matter of placing them
in the appropriate place. Most of them should probably go in
${ZDOTDIR:-$HOME}/.zshrc
before invoking zprezto init, to choose
the modules that should get loaded, and using the appropriate zstyle
calls form preferences (zstyle
is a kind of registry for shell configuration
native to zsh
)
Any tweaks to prezto’s behavior should go after invoking zprezto init
in zshrc
or, in ${ZDOTDIR:-$HOME}/.zlogin
. Note however that the
zlogin
(sysem or user) files will be sourced only for login shells.
That means, when logging in to a remote system via ssh for example or
when calling say, XTerm
or your favorite emulator by specifying you
want a login shell (by calling zsh -ls
instead of plain zsh
).
Otherwise, the zlogin
files are ignored.
Also, note that another difference between interactive login shells and
plain interactive shells, is that, besides sourcing zlogin
files,
interactive login shells also allocate a pseudo-tty (you can see them when
invoking w
. Login shells have a pty assigned, while interactive non-login
shells don't.)
Why is this designed this way? because login shells are assumed to be
the main point of interaction with a user while non login shells would
be spawned as sub-shells of a login shell , when executing scripts
that call zsh
as a command interpreter, for example, when the shebang is
#!/usr/bin/env zsh
or equivalent.
When launching a new terminal within an X11 session, it is safe to assume that you are already logged in so any terminal emulator will launch an interactive-non-login shell. Which is, per specification the correct behavior, but not the behavior most users expect.
There is a reason for this specified behaviour: zlogin
files should
be used for interaction oriented settings such as custom completion,
keybindings, tmux
session setup, and most alias
es.
The advantage of grouping all interaction oriented settings in
.zlogin
is that non-interactive shells (executing scripts via
zsh -c [script]
, the shebang, subshells or make
invoked shells,
for example) will not be burdened by additional config settings making
them faster and more responsive, as keybindings and aliases are not
even loaded at startup, after all, an executable non-interactive script,
should never call on keybindings or aliases (assuming they were properly
written to be portable)
Finally, it is a common source of frustration amongst graphical environment
users, to spend some time adding their customizations to .zlogin
only
to see them ignored when launching a new XTerm
or tmux
pane.
This can be solved by calling (or aliasing) your terminal emulator with
the required option to invoke a login shell, for XTerm
, for example
you would call xterm -e zsh -ls
on tmux you may add one of the following
lines to your .tmux.conf
:
#tmux.conf:
set -g default-command 'exec /usr/bin/zsh -ls' #this will make zsh a login shell AND a session leader
set -g default-shell '/usr/bin/zsh -ls'
Here is an examplefor i3wm on ubuntu
#i3wm.conf:
...
set $XTERM_CMD='xterm -e zsh -ls`
bind $mod+x $XTERM_CMD
...
if you want to replace your non-login shell on your emulator with a brand-new
shiny login shell you can issue exec zsh -ls
at your command prompt.
Doing this, however will not write that terminal’s history to file unless
INC_APPEND_HISTORY
was set when you strted the shell
INC_APPEND_HISTORY
makes zsh
append history entries as soon as the
command is finished. zprezto helpfuly sets INC_APPEND_HISTORY
,
INC_APPEND_HISTORY_TIME
, and SHARE_HISTORY
which makes your history
available immediately from different terminals on command completion,
and records execution time on the history file. Pretty neat, huh?)
You could tack-on all interactive customizations on zshrc
but you will
end up with bloated shells on non-interactive environments. Perhaps desktop
workstation users will not notice any difference, but in resource-constrained
environments it may be significant in terms of execution time and energy
consumption (v.gr when running a Raspberry PI on batteries or on a cell
phone environment such as termux
)
You may be thinking... why is zpreztorc
not invoked on .zlogin
instead
of .zshrc
? I believe it was a wise design decision, in order to
eliminate complexity by having the whole of prezto configured and
launched from a single point, as some of the modules need to be sourced
early in the startup process, editor
and gnu-utls
come to mind.
If invoked later on the startup, such as would be the case in .zlogin
would makee it easier to conflict with stuff users may add on zshrc
.
Also, it avoids not being loaded and causing user frustration if
the user launches non-login shells from graphical environments, as
discussed above.
Conclusion
For customization of your environment, use your .zshrc
after zprezto
has been invoked, or before to remove or activate packages via zstyle
calls
or
use .zshlogin
to override or tweak zprezto behavior. there is also
.zpreztorc
but you may want to leave that one alone.
In any case, this question is often brought up by users that use the
distributed runcoms as is which is a terrible idea, since doing
git pull
to update your distribution will clobber your customizations.
it’s a better idea to copy the distributed runcoms to your $ZDOTDIR
a
nd merge any changes an update may bring, if any (they are usually
confined to .zpreztorc
)
Troubleshooting
-
if prezto and some of your settings are loaded, but others are not; make sure you are running an interactive login shell (you should have a tty allocated, visible on the
w
list) and the$TTY
variable should be set, if that is not the case, check the above discussion, you can 'replace' your shell in situ by issuing the commandexec zsh -l
-
if you notice that none of your settings are loaded, check that
/etc/zshenv
does not disable them. In any case
setopt global_rcs
setopt rcs
in /etc/zshenv
should set them both. This issue would be extremely rare.
Authors
The authors of these files should be contacted via the issue tracker.