48 ms·
/.bashrc VS –/.profile VS –/.bash_profile
- adrusi 6y agoI generally use .profile as a place to declare configuration common to all shells, mostly environment variables like PATH and GOPATH and the XDG_*_PATH variables. Then I use shell specific files like bashrc and zshrc to configure shell-specific things, and make sure to source .profile.
- praptak 6y agoI use .profile for exporting environment variables and .rc for everything else. The 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.
- JoshTriplett 6y agoThat's the theory, but desktop environments often won't run your `.bash_profile` or `.profile` (so you won't end up with environment variables set in graphical apps), and then most terminal emulators don't run login shells by default (so you won't end up with environment variables set in your shells either). And even if your terminal emulator runs a login shell, you'll only have environment variable set in your shells, which will lead to problems when graphical apps don't have the same variables set.
- arminiusreturns 6y agoInteresting on the docker angle. Sometimes seeing the flow visually can help people: https://blog.flowblok.id.au/static/images/shell-startup-actual.png https://blog.flowblok.id.au/static/images/shell-startup-actu... https://i.stack.imgur.com/6LQgh.png https://i.stack.imgur.com/6LQgh.png
- MauranKilom 6y agoThat is... helpful, in a sense. I mean, it's not the fault of the graphic that it's so convoluted. 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?
- praptak 6y agoYou probably don't want to set aliases in all bash invocations, as they can royally screw scripts. For interactive shells the rc file is the proper place.
- laurent92 6y agoI’ve more often had my cronjobs screwed because they didn’t have the same aliases and PATH variables, rather than have them screwed because there was an alias for « ll ». The dichotomy between login and non-login environments is source of hours spent debugging, especially for beginner to average developers.
- JdeBP 6y agoActually, it is the fault of the graphic. 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 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 .
- RunningDroid 6y agoFor anyone confused by the title: the dashes are supposed to be tildes.
- mstade 6y agoThank you!
- vaccinator 6y ago/.bashrc is missing the dash too...
- nickthemagicman 6y agoAs a non Linux admin I struggle to understand why you would want the differential between a login and a non login script. 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.
- toast0 6y agoOften people have login scripts that print things like how much mail you have, etc. That's not necessary or desirable in a non-login context.
- CaptArmchair 6y agoThis article does a fair bit of explaining: [1] > 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/ 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-interactive-login-and-non-login-2ddp 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.
- deleted 6y ago[deleted]
- devnull255 6y agoIn Linux, processes scheduled in cron, systemd or other schedulers don't require and may sometimes have issues with the customizations in login scripts for interactive sessions. Login scripts may expect input from the user keyboard, or may depend on environment variables that exist when a login script is executed, but not when nonlogin scripts execute.
- NelsonMinar 6y agoI've been doing Unix for 30 years now and for the last 27 I've had all these scripts wired together. Or rather I have one script, then the others execute it. 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?
- barrkel 6y agoIt's simple enough. 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.
- barrkel 6y ago(Oh and you want to source your .bashrc from your .bash_profile so you start out with both env vars and everything else.)
- thespoonbends 6y ago> It's simple enough. > (Oh and ...) +1 to just dumping it all in ~/.bashrc
- deleted 6y ago[deleted]
- m463 6y ago. ~/git/stuff/bash_common.sh
- mehrdadn 6y agoJust don't try to apply anything you learn here to GitHub Actions images because the environments are kind of wild and broken across OSes and your scripts will not be triggered the way you would otherwise expect them to...
- LeoPanthera 6y agoI try to maintain a cross platform set of bash startup scripts but the biggest problem is that macOS and Linux don't follow the same rules. .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.
- Spivak 6y agoWhy not just guard your .bash_profile with something like if shopt -q login_shell; then ... and then just pretend it’s the Linux-y way?
- LeoPanthera 6y agoMy solution is that bash_profile simply runs bashrc, and bashrc starts with: if [ -n "$PS1" ]; then That seems to work fine everywhere.
- matheusmoreira 6y agoI agree, this is a much better solution. Multiple shell configuration files should be deprecated and replaced with this.
- funcDropShadow 6y agoremove the - in front of bash in the settings of Terminal.app. Then the terminal does not run a login shell but an interactive shell. You might have to add -i after bash for that.
- m463 6y agoI use 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 fi
- TwoNineFive 6y agoJust put a "echo ran bashrc" and "echo ran bash_profile" in each file. After a couple of weeks you'll have it all figured out.
- brbsix 6y agoThese rules of thumb are useful, but in the real-world I find the use of startup files to be very inconsistent across different platforms. Oftentimes I someone will override the default behavior, sourcing files in different conditions or order than you would expect. There's really no substitute to reading all the startup files in /etc and ~. Sometimes it's even necessary to inspect the binary itself when you find that a shell has been compiled with non-standard paths.
- beaugunderson 6y agoi'm a huge fan of bashrc_dispatch, which splits your bashrc into versions that run either all the time, when non-interactive, when interactive, or for login shells, as well as gives you functions like `shell_is_osx`, so you can share your configs across multiple operating systems: https://github.com/gioele/bashrc_dispatch https://github.com/gioele/bashrc_dispatch