217 lines
13 KiB
Markdown
217 lines
13 KiB
Markdown
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:
|
||
|
||
|
||
```bash
|
||
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:
|
||
|
||
1. Whether you are running a *login shell*
|
||
2. Whether the `RCS` and `GLOBAL_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`:
|
||
|
||
```config
|
||
#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
|
||
```bash
|
||
|
||
#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
|
||
---------------
|
||
|
||
1. 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 command `exec zsh -l`
|
||
|
||
|
||
2. if you notice that none of your settings are loaded, check that
|
||
`/etc/zshenv` does not disable them. In any case
|
||
|
||
```bash
|
||
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][4].*
|
||
|
||
- [Sorin Ionescu](https://github.com/sorin-ionescu)
|
||
|
||
[1]: http://www.kornshell.com
|
||
[2]: http://en.wikipedia.org/wiki/Fortune_(Unix)
|
||
[3]: http://www.manpagez.com/man/1/msgs
|
||
[4]: https://github.com/sorin-ionescu/prezto/issues
|