A seemingly new feature in OS X El Capitan (10.11 Beta) is Bash sessions (Terminal sessions). I now have a ~/.bash_sessions directory with history files, and my HISTFILE and HISTIGNORE envars are being overridden. How can I disable all of this functionality?
If you startup a new Bash session manually (i.e. bash -xl), you can see what is run on login.
You'll see the following line in the output:
....
+++ '[' '!' -e /Users/username/.bash_sessions_disable ']'
You can create a .bash_sessions_disable file in your home directory to disable this functionality.
This behavior is defined in /etc/bashrc_Apple_Terminal. It contains documentation comments describing what it does and how to customize it.
You can disable the per-terminal-session command history feature by setting SHELL_SESSION_HISTORY=0 in your ~/.bashrc script, as described here:
You may disable this behavior and share a single history by setting
SHELL_SESSION_HISTORY to 0. There are some common user customizations
that arrange to share new commands among running shells by
manipulating the history at each prompt, and they typically include
'shopt -s histappend'; therefore, if the histappend shell option is
enabled, per-session history is disabled by default. You may
explicitly enable it by setting SHELL_SESSION_HISTORY to 1.
Note that, although you can disable the entire session-state restoration mechanism by creating ~/.bash_sessions_disable, this is unnecessary just to disable the per-session command history feature, and is not recommended.
To summarize, this has to do with Apple's Resume feature. When this feature is enabled, when you quit an app or reboot, the next time the app opens it will open the windows that were previously open.
With regard to Terminal, three things have to be in place for this to happen:
$HOME/.bash_sessions_disable must not be present
System Preferences/General/Close Windows when quitting an app must not be checked.
When rebooting, select Reopen windows.
When you reopen Terminal, it will reopen the same windows and tabs you had before in the same screen positions. Additionally, if you have checked Terminal/Preferences/your-window-type/Windows/Resume/Restore-text-when-reopening-windows, it will restore the text on each screen.
Finally, and this relates specifically to the OP's question, it will restore the history in each window/tab if the following conditions hold:
SHELL_SESSION_HISTORY is unset or set to 1
shopt histappend is not set
HISTTIMEFORMAT is not set
If SHELL_SESSION_HISTORY is explicitly set to 1 in .bashrc, the last two requirements are overridden, that is, shopt histappend or HISTTIMEFORMAT could be set.
Additionally, attention needs to be paid to the HISTSIZE and HISTFILESIZE variables. They should not be too large or too small, and some advise to leave them unset so they take Apple's default values.
Everything so far written about this subject is accurate and useful, and the techniques already mentioned should be used in lieu of this. I'm going to mention a totally nuclear approach, just for the sake of entertaining alternatives, and also to expand further understanding of this subject.
The only reason I acquired this knowledge is simply because I was looking for an alternative solution to needing to create a ~/.bash_sessions_disable file; I would have instead preferred preventing the sessions behaviour from happening by just adding some lines to my existing ~/.bash_profile. Unfortunately, that is not possible without going nuclear, so the official answer is still the best approach.
Summary
When Bash first starts up on MacOS, it will first source /etc/profile, which in turn sources /etc/bashrc. The contents of that file include this line:
[ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM"
The $TERM_PROGRAM environment variable is only set by Apple's Terminal app. Printing the value of that variable returns Apple_Terminal. In other words, the /etc/bashrc file is attempting to source a /etc/bashrc_Apple_Terminal file if it both exists and is readable. It's in this file where MacOS does its special Bash session handling to tie into the Resume features of the OS.
After all that, Bash will then source any configurations a user has in their home directory (like ~/.bash_profile or ~/.bashrc). This being stated, there's no way to override all the work done in the /etc/bashrc_Apple_Terminal file on a purely configuration level (vs both configuration and creating a new file) without doing what the others have mentioned, namely, setting $SHELL_SESSION_HISTORY to 0 to eliminate session-based history, and creating a ~/.bash_sessions_disable to prevent the .bash_sessions directory from being created every time Apple's Terminal is started.
Nuclear Approach
The two possible alternatives to eliminate any of this new MacOS functionality would be to either 1) remove that last line from the /etc/bashrc file, or 2) rename or delete the /etc/bashrc_Apple_Terminal to something else.
After doing this, Apple's Terminal app will no longer behave differently than non-Apple terminal emulators.
Related
I set up some aliases in my .bash_profile on my Max OS X.
It works but when I'm opening a new tab I always have to load my .bash_profile file with this command:
source ~/.bash_profile
How can I make it work for every terminal I'm opening, even if I'm restarting my Mac or Linux computer?
If you use zsh , you can add source ~/.bash_profile
at the end of .zshrc file at the following path: /Users/YOUR USER NAME/.zshrc , then restart your Terminal/iTerm2 app.
Note that this file is hidden. You can press CMD + SHIFT + . in Finder to
see it, Or just open it in default text editor with the following command from terminal:
open ~/.zshrc
Update
You don't need to do this by hand, run the following command:
echo "source ~/.bash_profile" >> ~/.zshrc
* Dont forget to restart your terminal.
The files executed at the start may be several, usually ~/.bashrc for interactive, non-login shells. The kind I assume you are using.
If so, create an ~/.bashrc file and source ~/.bash_profile in it:
if [ -f ~/.bash_profile ]; then
. ~/.bash_profile
fi
This web site has a lot of information about this.
Study this image, as it is a condensed guide
If you do need to find out exactly which file is being executed, take a look at this web page. It has a lot of specific tests to find out what file is setting what.
Specific for Mac-OS (which is an exception and loads ~/.bash_profile) do as is recomended in the site linked in this answer AFTER you confirm that your bash is doing as explained there.
I know this is a pretty old post, but this problem comes and goes quite oftenly and a lot of laborous solutions are offered. The fact is: being aware of a simple info would solve this pretty fast and easy:
LINUX/Unix OS will load the profile files on startup following the rules below (some distros may have other files names, mainly for user local profiles, but the main rule follows this):
Login Shell
First and foremost: /etc/profile is loaded (global settings);
Next: ˜/.bash_profile (local user settings- other files may be found, like ˜/.profile, depending on the distro. Check documentation).
So, if you are in a Login Shell environment, put all your crazy stuff inside ˜/.bash_profile (or the file provided by your distro) and everything will be fine.
Non-login Shell
First and foremost: /etc/bashrc (some distros will load bash.bashrc);
The next file to be seeked and loaded is ˜/.bashrc
And that's why so many people (just like me) got frustrated having to source their ˜/.bash_profile every single time a Terminal was loaded. We were simply inserting info in the "wrong" file- regarding the kind of shell loaded (see above: login, non-login).
More details on variants of the files mentioned above and some info on login vs non-login shell can be found here.
Hope it helps \o/
What is the proper way to modify environment variables like PATH in Yosemite?
This is this question Setting environment variables in OS X? but specifically for yosemite since it doesn't work anymore.
Have you tried editing ~/.bash_profile?
Adding a line like this to bash_profile ought to do it:
export PATH=/usr/local/bin:$PATH
What shell are you using? I'm assuming you're using the default Bash shell. There's also Csh, Ksh, and Zsh.
The Terminal.app on Mac OS X by default starts a new login shell each time a window is open. This means that $HOME/.bash_profile or $HOME/profile is always executed when you open a new terminal window. You can set particular defaults in here. For example, I set PS1 and set -o vi.
NOTE: This may not be the case if you're using other Terminal apps like xterm. These open new terminal windows as just new shells. This means that you may not see the changes made in .bash_profile until you log out and log back in.
You can try editing $HOME/.bashrc and see if that helps.
What about other shells?
If you're using Kornshell (ksh), you need to edit the $HOME/profile and not $HOME/.bash_profile. If you're using Zshell (zsh), you're on your own. It's too wacky to describe here. Read the manpage for zsh and search for ZDOTDIR.
When you run a shell script, the $HOME/.bashrc is executed. Most people put something like this in their .bash_profile, so their .bashrc settings are included in a new terminal window:
[[ -x $HOME/.bashrc ]] && source "$HOME/.bashrc"
Some people set things they want to be set when they run a shell script, for example export $PS4="\$LINENO> ".
The $PATH is a bit different. You can set it in .bash_profile (I would not set it in .bashrc), But, Mac OS X has an automated why on how systemwide paths are set. A file called /etc/paths is used to set the default path for all users using either Bash or Kornshell via the /usr/libexec/path_helper program.
On my Mac, I set my $PATH to:
/usr/local/bin:/usr/share/bin:/bin:/usr/bin:/usr/sbin:/sbin:$HOME/bin
When I install programs, I usually install them under /opt when possible. Then, I link their binaries (where ever they're placed) to /usr/local/bin. This way, I don't have to keep building my PATH. Plus, it allows me to override system defaults. For example, /usr/bin/git is at 1.9.3. while my installed /usr/local/bin/git is at version 2.2.1.
One thing you should not do is modify /etc/profile because changes there may be replaced on OS X upgrades.
The problem is not with environment variables set and accessed from within /bin/bash or /bin/sh, but with envars that should be set for programs NOT executed from the shell; i.e. normal apps executed from the dock or Finder.
After finally getting things right with launchctl in Mavericks, Apple is in the process of changing things again. The useful subcommands of launchctl are now labelled as "legacy subcommands", some of which are no longer supported. That leaves a question mark over the others.
In any case, the most important subcommands are still available for now.
launchctl allows for the setting of the overall environment in which user processes execute. It appears that the overall user environment is inherited by all Terminal processes; i.e. all setenv variables are exported. It's a bit tricky to confirm that. In any case, you will still need your .profile and .bashrc to define functions and aliases, which are not supported by launchctl.
I go to some lengths to ensure that all of my launchctl vars are also defined in my profile. This enables me to set up the same environment on remote or VM linux systems, with a few minor tweaks.
Al of my setup is described in this blog post .
following solution worked for me.
Open Terminal
Click on Terminal Menu at right upper corner.
click on Preferences
Click on General
Change Shell open with to command and put /bin/bash in text box.
Now whatever configuration you do in ~/.bash_profile takes effect. Previously you were not using bash(were using ksh) that is why it was not reading .bash_profile.
After some search about it I created a ~/.hushlogin file and it worked, but only for new windows. Is there a way to make it work for new tabs too?
On Mavericks, creating the empty file ~/.hushlogin removes the line “Last login”, for new windows and new tabs.
On my Mac it works.
Solution
This is running OS X 10.8.3. I haven't tested it on other versions, but so long as Terminal has the above option, then it should work.
In Terminal.app, go to Preferences->Settings and select the profile you're using. Go to the 'Shell' tab and under the 'Startup' heading, check 'Run command:' and enter into the box:
login -fpql your-username /bin/bash
Substitute your-username with your actual Unix username. If you use a shell other than the default bash shell, replace /bin/bash with the full path to that shell (yes, even if you've already set it in Preferences->Startup.)
Make sure 'Run inside shell' is unchecked.
If you have the "Prompt before closing: Only if there are processes other than login shell and:" option selected, add "login" and "bash" to the list of processes it will not prompt for.
Make sure you have a ~/.bashrc file, since this will be the file bash uses on startup from now on rather than ~/.bash_profile. I just have one file reference the other using this method. You also need to be sure it sources /etc/profile.
Explanation
We want to run login with the -q option to tell it to supress the "Last login" message, even in the absence of a .hushlogin file. (As noted above, login will only look in cwd for that file, not your home directory, so you'd need a .hushlogin file in every directory you'd open a shell to, for that method to work.)
The problem is Terminal runs something like login -pfl your-username /bin/bash -c exec -la bash /usr/local/bin/bash when you create a new shell (I'm using homebrew's version of bash, hence the weird bash path at the end,) which lacks the -q flag.
Unfortunately, there's no way to directly change the arguments Terminal uses, so we just trampoline a new login session with login -pfql from Terminal's default login -pfl session. Inelegant, but it works.
We need to have the -q option and the path to bash to keep the "New windows/tabs open with: Same Working Directory" option working. If you don't care about that option, you can remove that flag and argument, and probably avoid the .bashrc stuff above.
you could just add a clear to your .bash_profile
Adding ~/.hushlogin is fine unless you want to open a new tab in the same folder, or open Terminal from Finder on the exact folder, in that case it won't work.
Changing a running command to another login is something I would like to avoid because of the strange unnecessary scheme login -> login -> zsh. You can see it in Activity Monitor, but also it will show up when you are quitting interactive programs (like, python repl) in the message that python, login and zsh are running.
Putting clear in ~/.zshrc is not ideal since on mac it just prints a lot of newlines (and if you scroll back, you'll see them).
The best way that I found up to this point is adding printf '\33c\e[3J' to ~/.zshrc (or in Terminal/Preferences/Profiles/Shell/Startup/Run command with Run inside shell checked). I chose beginning of ~/.zshrc file since startup command is running after it and if the ~/.zshrc file is heavy you can briefly see Last Login message before printf is executed.
This might be OS version dependent. On Terminal 2.3 (on 10.8), touching the file ~/.hushlogin suppresses the 'last login' message for new tabs as well as new windows. That is, it Works For Me.
Just in case it helps to work out what's going on (and in case you don't know), note that the 'last login' message is in principle coming from login(1), and not the shell. Or, more precisely, if a shell is invoked in a particular way (including starting it with the -l option), then bash will "act as if it had been invoked as a login shell" (zsh may have a similar feature, though I can't find it right now). Now, it could be that when Terminanl opens up a new tab in your OS X version, the shell is effectively simulating opening a login shell, and maybe getting this detail wrong. But if you have the 10.8 version of bash/zsh (namely 3.2.48 / 4.3.11), then I don't know what might be amiss.
A simple solution without changing anything related to login would be just to add the clear command in the end of your ~/.bashrc or ~/.zshrc file. It will clear the terminal in initialization from any initialization prints. It works for me very well.
On my MacOS Big Sur 11.1 it works.
I just installed GMT4 (Generic Mapping Tools) from MacPorts and have run into some serious issues with terminal...
When using the ls command in terminal I get the following:
-bash: ls: command not found
To fix this I've tried many things that I read many different places online. I've changed the following files to include /usr and /bin:
~/.bashrc
~/.bash_profile
~/.profile
Doing so gave me back the sudo command which I had previously lost.
However, I still am not able to use ls in a new terminal window without manually exporting the path("new session"). This has been causing problems when I'm running shell scripts that use system functions. So I'm starting to wonder what exactly those three files do and if maybe having three files doing the same thing is causing them to interfere with one another. If anyone can tell me where I need to add these PATHS that would be great; I dunno, maybe I can delete one of these files or something ELSE is conflicting. Right now I just run " export PATH=$PATH:/usr" in each new terminal window and it works for that session.
I'm running Mac OS X 10.6 on a early 2011 MacBook Pro with 4GB of RAM.
Background for those who are interested:
My end goal is to use Relax to model viscoelastic relaxation in a mid-oceanic ridge system to come up with some sort of constitutive law or power-relation between slip magnitude and the location of greatest tensional stress in the lithosphere due to normal faulting.
The Bash manual actually explains these files fairly thoroughly. However, the manual does not describe how these mechanisms are usually used in practice. What follows is a brief, abridged version of what is common best practice.
.profile is read at login by both sh and bash.
.bashrc is read by non-login Bash shells. By convention, .bash_profile sources .bashrc in turn.
.bash_profile is read at login by Bash. If this file exists, .profile is not read. By convention, .bash_profile should source .profile if it exists.
I have a TextMate bundle written in ruby that accesses the ENV hash to read shell variables.
It sometimes succeeds in reading this variable, and sometimes doesn't find it. I've been unable to figure out the pattern.
What dictates which shell variables will be visible to a TextMate bundle?
update
ah ha! When I launch TextMate from the command line, it works. If I launch it from the dock, it does not work (even if I then subsequently open a directory from the command line).
So the question now is, why does TextMate choose to pick up different environments in these cases, and is there a way to make them identical?
Textmate is launched via launchd, not from the shell.
Your $PATH will travel over if you run something directly from the shell (open -a Textmate does not work, open will not pass your environment to Textmate).
The ways to get around this are environment.plist, launchctl, or launchd.conf:
Setting environment variables in OS X?
update
If you edit /etc/launchd.conf and reboot, the changes will take effect. Each line can be a launchctl command like setenv VAR_NAME "VAR_VALUE". You could then run this file with launchctl your_file.
It's a pain having to reboot though. And if you want per-user environment settings, this is no good. Apple proposes ~/.launchd.conf could be used for user-specific settings, but has yet to implement this feature.
You could set a script to run on login with a LoginHook and LogoffHook (see Apple's documentation). Or, using LaunchAgents. For detailed directions on how to set up a LaunchAgent, look at nicksay's post on this Macworld post.
The launchctl setenv command doesn't seem to work while logged in. I'm currently banging my head against this.
I ran into basically the same problem you're having today (the Makefile bundle would not pass LIBRARY_PATH to gcc), and now I'm writing a python script that will read a file of variable assignments on login, store a copy of the current environment and that file with the assignments, and then unload all the variables on logout. That also reminds me, I should have an update option. I'll post a comment with the link to a github repo for it here when I'm done. If it works, that is.