The simple way is to invent a time machine, visit the various people who devised shell startup files and tell them to cleanly distinguish between three things:
- session setup, e.g. environment variables;
- session launching, i.e., e.g. starting a command-line shell or a window manager or running
startx;
- shell initialization, e.g. aliases, prompt, key bindings.
It's not too hard to get session vs. shell right in a portable way: login-time initialization goes into .profile (or .zprofile, or .login), shell initialization goes in .bashrc or .zshrc. I've previously written about .bash_profile, zsh vs. other shells, more about portability (mostly about bash), more about who reads .profile.
A remaining problem is distinguishing between session setup and session launching. In most cases, ~/.profile is executed when you log in and can double as both, but there are exceptions:
- If your login shell is (t)csh or zsh,
~/.login and ~/.zprofile is sourced instead of ~/.profile. Ditto for bash and ~/.bash_profile, but this is easily solved by sourcing ~/.profile from ~/.bash_profile.
- If you log in under a display manager (xdm, gdm, kdm, …), whether your
~/.profile is read depends on the version of the program, on your distribution (Linux or otherwise), and on what session type you choose.
- If you count on the display manager to start a session for you, your
.profile must set environment variables but not start a session (e.g. a window manager).
- The traditional configuration file for X sessions is
~/.xsession, doing both session setup and session launching. So the file can be essentially . ~/.xsession; . ~/.xinitrc. Some distributions source ~/.profile before ~/.xsession. Modern distributions only source ~/.xsession when you select a “custom” session from the display manager, and such a session is not always available.
- Your session manager may have its own way of setting environment variables. (That's an optional part of your desktop environment, chosen by you through a configuration file or by selecting a session type when logging in; don't confuse it with the session startup scripts provided by the display manager, which are executed under your user but chosen on a system-wide basis. Yes, it's a mess.)
In summary, ~/.profile is the right place for environment variables. If it's not read, try sourcing it from ~/.xsession (and start your X programs from there), or look for a system-specific method (which may depend on your distribution, display manager if any, session type if display manager, and desktop environment or session manager).