Index > Untangling Login Script Order

The point of this page isn't necessarily to explain the order of login scripts. That could be done better by reading the man pages. Instead I'm trying to show how best to organize login scripts for maximum compatibility across shells and display managers with minimal duplication.

Nearly every “Shell Tips & Tricks” article I read presumes that the reader uses Bash, and they also throw everything into ~/.bashrc regardless of whether that's the best place for something. Lots of users move from Bash to ZSH, and likely just move everything to ~/.zshrc without really looking into it. I use mksh but keep Bash around for the occasions when I want to use a feature of Bash that mksh doesn't implement.

This page will hopefully be helpful if you have a batch of config files you use across multiple environments (home, work, over SSH, etc.).

Terminal Login

There are two types of files run by shells:

POSIX—sh, dash

Upon login these shells first read /etc/profile and ~/.profile. An interactive shell will expand the value of the $ENV variable, often set in one of the profile files, and take that as the location of a config file to be run with each shell.


Korn Shells—ksh, mksh

Korn shells process files in the same order and location as POSIX shells do, except that if $ENV is empty or undefined interactive shells default to their own user rc file, ~/.kshrc or ~/.mkshrc as the case may be.

/etc/profile~/.profile$ENV OR ~/.kshrc


On login, BASH will read /etc/profile, and then read the first readable file of these three: ~/.bash_profile, ~/.bash_login, and ~/.profile.

A non-login, interactive BASH shell will process the contents of ~/.bashrc. Unlike other shells, an interactive login BASH shell will not read its runtime config file.

BASH can be told to act like a POSIX shell if started with the --posix option, or if it is called from a symlink named sh.

So when logging in: /etc/profile~/.bash_profile OR ~/.bash_login OR ~/.profile

And when not logging in: ~/.bashrc

If you're logging in with BASH and want it to process your ~/.bashrc file, add the following to one of the profile files:

if [ -n "${BASH}" ] && [ -n "${PS1}" ] && [ -r "${HOME}/.bashrc" ]; then
    . ~/.bashrc


ZSH is the most involved regarding its startup files:

  1. /etc/zshenv and then ~/.zshenv
  2. If a login shell: /etc/zprofile and then ~/.zprofile
  3. If an interactive shell: /etc/zshrc and then ~/.zshrc
  4. If a login shell (again): /etc/zlogin and then ~/.zlogin

If called by a symlink named sh or ksh, it will try to act as they do, above.

ZSH is the only shell to not source ~/.profile during login. If you want your environment set in ~/.profile, just add the following to ~/.zprofile:

[[ -r ~/.profile ]] && source ~/.profile

X Login

xinit and startx

These utilities run the shell script ~/.xinitrc, or /etc/X11/xinit/xinitrc if not found. ~/.xinitrc usually contains any X utilities you want autostarted, and the window manager at the end.

To call these commands, you need to login first, to you'll have already run your shell scripts, above.


  1. /etc/profile
  2. ~/.profile
  3. /etc/xprofile
  4. ~/.xprofile
  5. Chosen Premade Session (KDE, GNOME, Openbox, etc.) or ~/.xsession

~/.xsession is a shell script similar to ~/.xinitrc mentioned above.

Debian and Debian-based distributions also process ~/.xsessionrc after ~/.xprofile and before the chosen session. This script can do any configuration desired, like ~/.xsession, but should not start the window manager.


XDM does not source any profiles, does not handle the choosing of session types, and skips straight to sourcing ~/.xsession.


The problem with working across multiple login types here isn't xinitrc or a premade session in a display manager. ~/.xinitrc can source ~/.xprofile to set up the X environment, and both methods will source ~/.profile.

The problem is ~/.xsession. Ideally we should simply source ~/.xinitrc from ~/.xsession, and this will work perfectly with xinit or XDM, but will in turn source ~/.xprofile a second time with newer display managers. To be compatible across XDM as well the problem is worse, as we'll need to source ~/.profile, again, processing a file twice with newer managers.

Putting It All Together

Coming Soon™