/.bashrc VS –/.profile VS –/.bash_profile
leimao.github.io
leimao.github.io
I get in theory why I'd want interactive login shells to have a fancier / more complex environment than others. Maybe I should care more about optimizing startup time of non-interactive shells. But really, who has the time to figure that stuff out?
Put env vars in bash profile and functions, aliases and other non-env (completion, nvm, rvm etc) in bashrc.
Put the latter into the former and they aren't inherited. Put the former into the latter and path appends and other non-idempotent edits to env vars don't work correctly. Though I personally use some functions to make sure my path edits are idempotent for ease of iteration when editing.
> (Oh and ...)
+1 to just dumping it all in ~/.bashrc
. ~/git/stuff/bash_common.shhttps://blog.flowblok.id.au/static/images/shell-startup-actu...
But can someone explain why it has to be this convoluted? If I parse it correctly, there is no single place where I could place an alias and have it be available in all bash invocations (e.g. green and yellow arrow don't go through any common files). Without resorting to sourcing one from another, that is.
Is there a method to this madness?
For interactive shells the rc file is the proper place.
The dichotomy between login and non-login environments is source of hours spent debugging, especially for beginner to average developers.
One flowchart works like a conventional flowchart but shows all of the command-line overrides as separate decisions. They are, but that obscures the actual simplicity of the system. The other flowchart has an odd way of representing the decisions, not using decision nodes. And the colouring isn't even consistent, and is downright wrong in one place.
There are really only four possibilities: login interactive shell, login non-interactive shell, non-login interactive shell, and non-login non-interactive shell.
Whether a shell is login/non-login, and whether it is interactive/non-interactive, are determined from a combination of things including standard I/O file descriptors and process arguments; standard-conformant mode differs from native mode in almost all shells; and shells like the Z shell have several compatibility modes for other shells; but there are just four outcomes, one of which (login non-interactive shell) is rare in practice (https://unix.stackexchange.com/q/304447/5132).
And the basic idea is that personal convenience shell aliases and shell functions, key bindings, prompts, completion controls, and all of the other UI parphernalia such as history files and mailboxes to monitor, are things that you should only be setting for interactive shells. For the Z shell in its native mode, for example, that's the domain of the global zshrc and the per-user .zshrc . For the Korn and Almquist shells, similarly, that's the domain of the file named by the ENV environment variable. For the C shell it is the domain of the global cshrc and per-user .cshrc .
That blog post was my primary reference after zshall(5) when I decided to blow away the years of cruft I'd built up, start over, and rewrite my (Zsh) shell init files from scratch -- and I've been amazed at how much more organized and manageable it all is since then!
Prior to switching to Zsh, I had gotten to the point of just dumping everything in one file and making sure it was sourced (by bash) in all instances.
--
[0]: https://blog.flowblok.id.au/2013-02/shell-startup-scripts.ht...
.bash_profile is only supposed to run after logging into an interactive shell, and .bashrc is for every new shell.
But macOS runs .bash_profile every single time you open a new shell window, so you have to do some creative scripting to make it do what you want to do.
if shopt -q login_shell; then
...
and then just pretend it’s the Linux-y way?if [ -n "$PS1" ]; then
That seems to work fine everywhere.
OS=`uname -s`
if [ "$OS" = "Darwin" ]
then
# all the mac stuff
add_plist () {
/usr/libexec/PlistBuddy -c 'Delete :'"$1" ~/.MacOSX/environment.plist >/dev/null
/usr/libexec/PlistBuddy -c 'Add :'"$1"' string "'"$2"'"' ~/.MacOSX/environment.plist >/dev/null
}
if [ ~/.bashrc -nt ~/.MacOSX/environment.plist ]
then
mkdir -p ~/.MacOSX
add_plist PATH "$PATH"
add_plist HISTFILESIZE "$HISTFILESIZE"
add_plist HISTSIZE "$HISTSIZE"
add_plist HISTTIMEFORMAT "$HISTTIMEFORMAT"
add_plist HISTCONTROL "$HISTCONTROL"
add_plist PS1 "$PS1"
fi
fiThe rationale is that exported env variables are inherited (and I most probably don't want them overwritten by child interactive shells reading .*rc) and other things (e.g. aliases) aren't and I probably want them set for every interactive shell.
One interesting thing I discovered was there are system-wide profile and bash profile scripts.
/etc/profile /etc/.bashrc
In case you need to set these for every account.
That's not necessary or desirable in a non-login context.
> The primary thing to understand is that the rc files are for all shell invocations while the profiles are strictly for interactive shells. An interactive shell is where you (end user) types the command while an non-interactive shell is when shells are launched by other programs such as a script with #!/bin/bash as SHEBANG value
[1] https://www.golinuxcloud.com/bashrc-vs-bash-profile/
So, what are use cases in which a non-interactive shell is launched? One example is a cron jobt that runs every night. It's basically the "cron" process executing a command which could be a bash script. Another example would be startup scripts that launch background processes and services which you'd find in /etc/system.
There's a distinction between interactive v. non-interactive and login v non-login as well [2]
https://dev.to/bijaykumarpun/linux-shells-interactive-non-in...
Typical issue would be adding something to your PATH variable in .profile, having your script work just fine in a shell, but having it fail when you run it as a cron job because .profile never gets sourced by cron.
If there is some non-interactive use of bash, I just want a clean environment, and everything scp or ssh needs should be on the standard $PATH.
There's no point in putting anything in .profile either, because if I am running an interactive session, I will be using bash. I don't care about the config for dash or whatever.
And any scripts should completely specify their required functions, $PATH and whatever inside the script itself. Use 'source' to pull in common functions.