Whenever bash/zsh/etc was launched with the --login
flag or by the systemd/init process determines whether it is a “login shell” (although because there’s two ways to create this, figuring out if you are in a login shell isn’t 100%.
These will run the first readable profile script they encounter. The specific shell determines where it looks but for (some versions) of bash for example the order is .bash_profile
, .bash_login
, .profile
. This varies by version a bit but isn’t too terribly hard to guess. Also there are logout scripts that will run on shell exit (their names are similar but not completely homoiconic). All this can be disabled with --noprofile
When launched with -i
(which is not short for --interactive
but instead a shopt thing) or I believe via just bash
/zsh
without the -c
parameter, This is again not straightforward to test for whether you’re interactive or not. Online people say to check for echo $-
containing an i
but I’ve found situations where that doesn’t do it.
In this case it will run your rc files, again going through an order which seems to vary slightly but most people just do ~/.bashrc
or ~/.zshrc
. The specific file that is called can be controlled with --rcfile
and disabled by --nonrc
. These only work if your shell is actually in interactive mode. Note that if you use the -c
parameter but not the -i
one, then you will not be in interactive mode. Also note that profile is not called (unless you call it explicitly in your rc or something).
If a shell is both --login
and -i
interactive then it just seems to be treated as a login shell although this doesn’t seem to be explicitly documented
There seems to be a BASH_ENV
that you can set that points to a script file that will be run in…some situations. This doesn’t seem terribly common so I didn’t dig in to much. Not sure if zsh even bothers with this
There is also something around naming bash sh
that makes it work in a mode where it tries to be compatible to sh
, again didn’t dig in too much
Also keep in mind that environment variables are copied into a process from its parent process. Most (but not all) processes do have a login shell somewhere in their parent call chain so you will see any env variables set there. Many have an interactive (or one that explicitly sourced rc files) shell in their parent chain as well
This chart is useful but not 100% correct