Why VS Code on macOS suggests add $PATH to zprofile instead of zshrc? - macos

I am studying zsh on macOS and I find when adding software to $PATH you are usually supposed to write them in .zshrc (zsh). However, Visual Studio Code documentation suggests
To add VS Code to your path, to do so run the following commands:
cat << EOF >> ~/.zprofile
# Add Visual Studio Code (code)
export PATH="\$PATH:/Applications/Visual Studio Code.app/Contents/Resources/app/bin"
EOF
I find zprofile set the environment for login shells while zshrc sets the environment for interactive shells. However, I cannot really see differences between two methods on macOS terminal since each terminal tab is a login session on macOS by default.
Is there any reason why Visual Studio Code on macOS suggests add $PATH to zprofile instead of zshrc and what will be the good practice?

If you read this and this answer as well as the man page (man zsh under STARTUP/SHUTDOWN FILES) you might come to the following conclusion:
You are using MacOS, therefore every zsh you open is a login shell, that way you made sure, that .zprofile will always be read. So if you append your $PATH in your .zprofile and and use zsh as a non interactive-shell you will be able to access your appended $PATH. This might happen in a script of if other programs try to use a program that you added to your $PATH.
Now on the other hand if you added VSCode to your .zshrc it will always be available in an interactive shell. Which mean if you use VSCode 'manually' you will always have it at your disposal in zsh. But other programs/scripts might not find it.

If you set environment variables in .zshrc or .zshenv it can be awkward if you want to use a different value. Say you install a different version of vscode in a different directory. Any new shell will reset the environment variable instead of inheriting it. As environment variables are inherited, there is no need to reset them for every new shell. So .zprofile is often a better choice - the variable is set on first login and inherited but can be changed for a shell and its children. Another option is to set them from .zshenv but use a condition around them such as if [[ ! -o privileged && -o rcs && $SHLVL = 1 ]]; then

Related

Force reload PATH in bash

I'm developing PHP on Windows machine and due to various old project I need to switch PHP version frequently. I wrote a script that edits $PATH environment variable and it works without a problem.
I'm using Git Bash as a CLI tools. All I need to refresh $PATH is to close the app and load it again. Simple enough, works well, php -v starts reporting correct version.
Problem is, I'm also using Git Bash integrated in Git Extensions and PhpStorm. Turning Bash off inside them doesn't work. Neither does restarting the applications themselves. I'm forced to restart the PC, which is of course annoying.
Is there a way to force Bash to reload environment variables via code?
Answers I found suggest running
bash
source ~/.bashrc
source ~/.bash_profile
But none of those work.
In PowerShell working solution is this:
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
so I need something similar but suited for bash.
Here is the way
# Temporary environment variables
$ export PATH=/you/can/set/git/path/here
on windows it will be something like C:\Users\your\path
#Confrm if its set
$ echo $PATH
Also in Bash you can check what variables are there with $ env
Writing it out jumpstarted my mind and I figured what I had to do.
Since I already have a script that changes PATH in Windows, I can use the same script to edit files bash_profile and bashrc.
In the end this is enough to make it work, first line is changed dynamically:
PATH=/c/wamp64/bin/php/php5.6.40:$PATH
export PATH
alias reload='source ~/.bash_profile'

Changing the VSCode integrated shell's prompt on MacOS X

Having just installed VScode I have noticed as it uses Bash by default on OSX, with the shell's default prompt of bash-3.2$; consequently, I cannot see the current working directory. It means having to type 'pwd' and 'ls' quite frequently which is obvious quite tedious.
I have tried changing the default shell in the settings to
"terminal.integrated.shell.osx": "/Applications/Utilities/Terminal.app"
or
"terminal.integrated.shell.osx": "/Applications/iTerm.app"
This doesn't seem to work, have I made a mistake here?
I would also like to know if I am limited to bash, can I configure it to display the working directory instead of simply bash-3.2$ ?
See this screenshot of how the VSCode integrated terminal looks by default
Thanks in advance!
I use Ubuntu, and only add the following lines to the end of ~/.bashrc:
if [ "$TERM_PROGRAM" = "vscode" ]; then
PS1='\$ '
fi
Try it and let me know if it works on your OS.
You can set your prompt to contain the current working directory by defining PS1 as follows:
PS1="\w $"
The $ is just some visual sugar. There all manner of things you can have your prompt display. Put the definition in your ~/.bashrc or ~/.profile for it to be set when you login.
Check out the Controlling the Prompt section of the GNU Bash manual for details.
If you are not accustomed to editing your bash init files you can do it with Visual Studio Code by going to View->Command Palette and execute the following command (one-time only):
Install 'Code' command in path
Then open the integrated terminal and type the following:
code ~/.bashrc
Then add the PS1 definition to the bottom of that file.

Pressing <tab> after typing 'export VARIABLE=~/' clobbers the 'VARIABLE='

I'm experiencing the following behaviour in bash that I find very annoying:
Type export VARIABLE=~/
Now I'd like auto-completion for the next segment of the path, so I press <tab>.
Bash clobbers the VARIABLE=, leaving just export ~/.
Why is this happening?
My bash version is 4.3.33, OS is Debian testing, terminal is Konsole.
Verify that $COMP_WORDBREAKS includes an =. If not, try this:
COMP_WORDBREAKS+==
If the export completion works to your satisfaction after that, then you need to figure out what startup file is changing COMP_WORDBREAKS.
For example, if you've installed node.js, the npm completion script (in /etc/bash_completions.d/npm removes = and # from COMP_WORDBREAKS.
Many completion scripts, somewhat annoyingly, change global settings. (For example, the standard Debian/Ubuntu completion scripts enable the extglob shell option.)

Setting environment variables in Yosemite

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.

~/.profile, ~/.bashrc, and ~/.bash_profile not running on new terminal start up

I am trying to create a permanent alias for my terminal. I put the alias in my ~/.profile, ~/.bashrc, and ~/.bash_profile files, previously empty. When I start a new terminal, bash does not recognize the alias, but if I source any of them, it does. Why are these not getting run when I open a terminal? I am on OSX.
Newer MacOS versions use zsh as the default shell for both Terminal and iTerm2. Run echo $SHELL to confirm if this is the case for you.
Zsh looks for a .zshrc file upon shell startup, so to continue using zsh while sourcing the contents of your bash profile, you can run the following:
echo "source ~/.bash_profile" >> ~/.zshrc
Open a new terminal window for the changes to take effect.
Two things need to happen here when using iTerm to get the loading of dotfiles to work.
First you should add the following to your .bash_profile
[[ -s ~/.bashrc ]] && source ~/.bashrc
Secondly you will need to ensure that in iTerm preferences your terminal is set to launch a login shell.
Hope this helps!
Using the default mac terminal, what worked for me was to add a command to run on start up to source my .bash_profile.
Preferences > Profile > Startup > Add command 'source ~/.bash_profile'
Mac terminal preferences window screenshot
Might be considered to be a bit hacky, but it does the trick.
Adding source ~/.profile to my .bash_profile worked for me.
As of High Sierra, both Terminal and iTerm want to load ~/.profile first. So I suggest you put one line in your .profile to make your Mac work like other Unixes:
source ~/.bash_profile
By editing this one file, you won't have to search through the menus of multiple apps to override Apple's bizarre behavior in each.
As of Catalina the default shell is now zsh. You can change it back to bash with chsh -s /bin/bash and that should load your .profile or .bash_profile
Why are your shell's initialization files not loading?
As with most things, It Depends ™
I recently experienced the same phenomenon and went through the following exercise to resolve it:
I use iTerm. iTerm runs a login shell by default. Verify in iTerm Preferences > General > Command > (*) Login Shell
Therefore, I know that ~/.bash_profile will always be called.
Knowing that, I put the following in my ~/.bash_profile file:
for file in ~/.{bashrc,bash_exports,bash_aliases,bash_functions}; do
[ -r "$file" ] && source "$file"
done
unset file
Notice that I use separate files for .bashrc, .bash_exports, etc. It keeps things separate and simple.
Note also that /etc/profile is loaded first, but since I have never used that system wide init file, I knew that that was not my problem. For details check out $ man bash
So, I started with my ~/.bash_profile file.
I found that when I installed Canopy Express that it's installer replaced the contents of my ~/.bash_profile file with the following content:
# Added by Canopy installer on 2017-04-19
# VIRTUAL_ENV_DISABLE_PROMPT can be set to '' to make the bash prompt show that Canopy is active, otherwise 1
alias activate_canopy="source '/Users/lex/dev/python/User/bin/activate'"
# VIRTUAL_ENV_DISABLE_PROMPT=1 source '/Users/lex/dev/python/User/bin/activate'
p.s. Canopy is an excellent, free python IDE, that I highly recommend.
Fortunately, I backup my ~/.bash* files so restoring that was easy and quickly fixed my issue.
My advice would be to understand the order of calls to your initialization files and start with the first one and work your way through them until you find the problem.
Oh, and you may want to verify which shell you are using (I use bash):
~ $ echo $SHELL
/usr/local/bin/bash
I am guessing you may use another shell, such as bash, tcsh, sh, zsh etc.
Put source .bash_profile into your appropriate 'bashrc' file will make the auto loading recovered, i.e.
.login for tcsh, .bash_profile for bash, .zshrc for zsh
My issue was solved by unchecking Preferences > General > tmux >
Use "tmux" profile rather than profile of the connecting session
Most likely, you need to create the files yourself as they appear not to exist by default. You should give them execute permission to make them run.
~ % sudo chmod 700 ~/.bash_profile
Also, you should check the ownership of the files. They should belong to current user rather than root. Otherwise, you will get permission denied error.
~ % ls -a -l
~ % sudo chown <user_name> ~/.bash_profile
Finally, please note that bash looks in your home directory for .bash_profile, .bash_login, and .profile in order. Bash will stop looking if the first is found.
This means if you have both .bash_profile and .profile files, the .profile will not run.
For more information
Hope this would help you.
Little late to the party but it seems that the file .zprofile is the equivalent to that of .bash_profile when loading zsh. I used this instead to execute a few commands on startup. Of course this only valid for a specific iTerm setup with zsh.
https://zsh.sourceforge.io/Intro/intro_3.html

Resources