PATH set before /etc/zshenv

I would try this approach to track down the source of /opt/texbin in your PATH variable:

  1. To get a list of files, which are actually read in (e.g. a non-standard file might be sourced by another file!), you can invoke zsh with the SOURCE_TRACE option enabled:

    $ zsh -o sourcetrace
    +/etc/zshenv:1> <sourcetrace>
    +/home/user/.zshrc:1> <sourcetrace>
    +/home/user/.zcompdump:1> <sourcetrace>
    +/home/user/.zshrc-last:1> <sourcetrace>
    
  2. Check these files, where the PATH variable come into play:

    $ grep -ie "path.*=" files_from_step_1
    

    The case insensitivity is crucial, since zsh uses the array $path, which automatically gets converted to the bash-like colon-separated list $PATH and vice versa.

  3. If still not lucky, try to include a debug message in /etc/zshenv, where commands are first read from:

    print -l $path
    

    This will give you a nice list of the PATH variable, which zsh inherits from its parent process (display manager, init process, etc.).*

  4. If the path is indeed inherited from the starting process, it is crucial to know which processes are relevant:

    $ pstree -apH $$
    

    This produces a process tree, where the shell process (pid in $$) is highlighted. Check the config files for these processes, too, and keep in mind that

    • source /some/file or . /some file can also alter the PATH
    • if you edit e.g. /etc/profile in your current console, log off and log in again, the parent process (X logon manager) might still have the old environment.+

* As you have written, the PATH already contains /opt/texbin before /etc/zshenv is read, checked by set -x in /etc/zshenv. I get no output with this technique, but with my step 3, hence I included the other steps in my answer as well.

+Suffered myself badly due to this behavior some time ago...


The PATH variable that is passed to your shell at log-in is defined in /etc/login.defs. There are two setups here, ENV_SUPATH and ENV_PATH. Depending if you login as root or as a user, one of the two is passed to the shell via the environment variable PATH. After the PATH variable is passed to the shell, any additional changes are controlled by the shell's start-up scripts.


The correct way to activate execution trace or source trace at the time /etc/zshenv is loaded is to activate it at the shell command: zsh -l -o xtrace, zsh -l -o sourcetrace -- be sure to try with the -l option, since the path element might only be added at login.

Beside this, if you are still getting a path element added before /etc/zshenv is loaded, you could check for a ~/.pam_environment file. This is the user-local version of the /etc/environment file and is loaded at about the same time, before the shell or user environment. Check the man page "pam_env" for more details about the format used - it is different for the user file.

One other minor possibility is the ENV environment variable. When a SH-compatible shell is started in SH-compatible mode, the file whose path is in ENV is loaded as a startup file before anything else. Search your shell's documentation for more detail. login.defs is also used at login and by various user/login utilities, but /etc/environment is the standard for all modern login systems and is prefered for establishing the PATH variable.