macOS shell: JAVA_HOME is empty inside script - bash

I have macOS 10.11.6. The JAVA_HOME is set in the .bash_profile as
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
export PATH=$JAVA_HOME/bin:$PATH
From command line, I can see it
>echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home
But, the JAVA_HOME is empty, when I run the following script
#!/bin/sh
SHELL=/bin/sh
export SHELL
echo $JAVA_HOME
if [ -n "$JAVA_HOME" ]; then
#do something
else
echo JAVA_HOME is empty
fi
Even if I use #!/bin/bash in my script, the JAVA_HOME is still empty.

TL;DR
Depending on how you run your scripts, you may need to put your exports into ~/.bashrc for interative shells, or directly into your script or crontab so that it doesn't rely on exports from your user's shell.
Bash Startup Files
Simplistically, the ~/.bash_profile script is sourced for login shells (e.g. /bin/bash -l), while the ~/.bashrc file is sourced for interactive shell (e.g. /bin/bash -i). It's actually a bit more complicated than that, but the above should get you pointed in the right direction.
See Also
https://www.gnu.org/software/bash/manual/html_node/Invoking-Bash.html#Invoking-Bash
https://www.freebsd.org/cgi/man.cgi?query=bash#INVOCATION
man 1 bash

I configure mine like this:
# configure Java http://www.jenv.be/
# install Java: brew cask install java, brew cask install java7
# set global default: setJavaGlobal 1.7, jenv global 1.7
# set local folder default: jenv local 1.8
#
JENV_HOME=$HOME/.jenv
export PATH=.:$PATH:$JENV_HOME/bin
eval "$(jenv init -)"
export JAVA_HOME="$HOME/.jenv/versions/`jenv version-name`"
alias jenv_set_java_home='export JAVA_HOME="$HOME/.jenv/versions/`jenv version-name`"'
And some related shell methods I use in my .bash_profile :
setJavaGlobal() {
jenv global $1;
jenv_set_java_home
echoJavaSetup
}
setJavaLocal() {
jenv local $1;
jenv_set_java_home
echoJavaSetup
}
echoJavaSetup() {
echo --------------------
echo NEW JAVA SETUP:
echo " PATH: $PATH"
export JAVA_VERSION=`java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'`
echo " JAVA: $JAVA_VERSION, $JAVA_HOME"
jenv versions
echo --------------------
}
removeJavaLocal() {
rm -rf ./.java-version
}
showJava() {
echo --------------------
echo EXISTING JAVA SETUP:
echo " PATH: $PATH"
export JAVA_VERSION=`java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'`
echo " JAVA: $JAVA_VERSION, $JAVA_HOME"
jenv versions
if [ -f ./.java-version ]; then
echo "Using Java LOCAL DEFAULT. Not using global default! Run command 'removeJavaLocal' to change to global default."
fi
echo --------------------
}

Related

Why my file does not get sourced from bash script?

I have a bash script where at some point, I want to source the ${HOME}/.profile file which should add ${HOME}/.local/bin to the $PATH. But when I check the path with echo $PATH, ${HOME}/.local/bin is absent as if the source did not happen. What am I doing wrong?
if command -v pip3 &>/dev/null; then
echo "Pip is already installed."
else
echo "Pip is not installed. Installing Pip..."
cd ${HOME}/Downloads
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
su -c "python3 get-pip.py --user" "$SUDO_USER"
cat <<-'EOT' >> "${HOME}/.profile"
# set PATH so it includes user's private .local/bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
EOT
source "${HOME}/.profile" #this is not happening!!!
rm ${HOME}/Downloads/get-pip.py
echo "Pip has been installed."
fi
Thanks in advance.
EDIT: Fixed the script syntax as suggest by Kusalananda.
A script can't modify the environment of the shell from whence it was executed.
Sourcing ~/.profile in the script will not set the path in the interactive shell that originally started the script. To do that, you would have to source your script.
Also, your here-document would need to be quoted, or the current values of HOME and PATH would be inserted into the .profile file:
cat <<'PROFILE_END' >> "$HOME/.profile"
# set PATH so it includes user's private .local/bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
PROFILE_END
Also note that if the user is a bash user with an existing ~/.bash_profile file, then the ~/.profile file will be ignored for that user when a new login shell is started.
I'm further unsure why you su to $USER. It seems like an unnecessary step.

Getting error: bash: parse_git_branch: command not found

I am running the command:
sudo bash
But I keep getting an error on my terminal that says,
bash: parse_git_branch: command not found
Here is my .bash_profile file
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\u#\h \[\033[32m\]\w - \$(parse_git_branch)\[\033[00m\] $ "
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM$
if [ -f ~/.git-completion.bash ]; then
. ~/.git-completion.bash
fi
export PATH=/usr/local/bin:/Applications/XAMPP/xamppfiles/bin:$PATH
export PATH=/bin:/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:$PATH
export EDITOR='subl -w'
export JAVA_HOME=$(/usr/libexec/java_home)
export JAVA_HOME=$(/usr/libexec/java_home)
export JAVA_HOME=$(/usr/libexec/java_home)
Thanks in advance.
The problem is that parse_git_branch is defined in .bash_profile, but not exported. When you run sudo bash, it starts an nonlogin shell that sources .bashrc instead of .bash_profile. PS1 was exported and so is defined in the new shell, but parse_git_branch is not.
Typically, you would define both PS1 and parse_git_branch in .bashrc and export neither of them. macOS is a little different from Linux, in that a terminal emulator starts a login shell instead of an ordinary interactive shell. A good practice is to put the definitions in .bashrc, then source .bashrc from .bash_profile.
Here's how I would split up your existing .bash_profile:
In .bashrc:
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
PS1="\u#\h \[\033[32m\]\w - \$(parse_git_branch)\[\033[00m\] $ "
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM$
if [ -f ~/.git-completion.bash ]; then
. ~/.git-completion.bash
fi
In .bash_profile:
# Many of the paths you were adding to PATH should already be
# there in the default configuration; run /usr/lib/path_helper
# to see the default.
PATH=/Applications/XAMPP/xamppfiles/bin:/usr/local/sbin:$PATH
export EDITOR='subl -w'
export JAVA_HOME=$(/usr/libexec/java_home)
[[ -f ~/.bashrc ]] && source ~/.bashrc
What fixed the issue in my case was adding the hashbang (#!/bin/bash - or could be tcsh in the end in your case) to the beginning of my .bashrc.
Without hashbang at the top of .bashrc the function still applied to PS1 but only within the main partition (on my SSD), but when I tried to manipulate git repositories on another mount (an extra HDD) I had this message.
So just adding #!/bin/bash and then reloading .bashrc (by doing source ~.bashrc) fixed this issue for me.
By looking at your .bash_profile, it seems you have forgotten to add the keyword function before parse_git_branch() {}
Try changing to,
function parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
After that, reload your .bash_profile and see if it works.
Reference: Functions in Bash.

SublimeREPL: mesg: ttyname: Inappropriate ioctl for device

When I try source ~/.profile in SublimeREPL for the bash shell I get the error above. Any ideas how to resolve this?
So this is the contents of my .profile. I start a bash instance inside bash I can source things normally.
##
# DELUXE-USR-LOCAL-BIN-INSERT
# (do not remove this comment)
##
echo $PATH | grep -q -s "/usr/local/bin"
if [ $? -eq 1 ] ; then
PATH=$PATH:/usr/local/bin
export PATH
fi
test -r /sw/bin/init.sh && . /sw/bin/init.sh
# Setting PATH for Python 2.7
# The orginal version is saved in .profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
export PATH
##
# Your previous /Users/jonathan/.profile file was backed up as /Users/jonathan/.profile.macports-saved_2013-05-18_at_17:57:46
##
# MacPorts Installer addition on 2013-05-18_at_17:57:46: adding an appropriate PATH variable for use with MacPorts.
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
# Finished adapting your PATH environment variable for use with MacPorts.
### Added correct profile for Postgres
export PATH="Applications/Postgres.app/Contents/MacOS/bin:$PATH"
### Added by the Heroku Toolbelt
export PATH="/usr/local/heroku/bin:$PATH"
# if running bash
if [ -n "$BASH_VERSION" ]; then
# startup virtualenv-burrito
if [ -f "$HOME/.venvburrito/startup.sh" ]; then
. "$HOME/.venvburrito/startup.sh"
fi
fi
### Added for Amazon CLI
export JAVA_HOME=$(/usr/libexec/java_home)
# ~/.profile: executed by Bourne-compatible login shells.
if [ "$BASH" ]; then
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
fi
mesg n

Something in my bashrc file causing bash: command not found?

When I open up a new shell I get:
Last login: Sun Mar 23 10:14:46 on ttys000
-bash:  : command not found
I'm not totally sure how to figure out what's going on there, as its not totally clear which command its talking about.
Is it likely something in the .bashrc file?
HISTSIZE=10000
HISTFILESIZE=20000
export CLICOLOR=1
export LSCOLORS=ExFxCxDxBxegedabagacad
export PS1="\[\e[01;32m\]\h \[\e[01;34m\]\W \$(parse_git_branch)\[\e[01;34m\]$\[\e[00m\] "
export PYTHONSTARTUP=/Users/JimShook/.pythonstartup
export WORKON_HOME=$HOME/.virtualenv
source /usr/local/bin/virtualenvwrapper.sh
# Setting PATH for Python 2.7
# The orginal version is saved in .bash_profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
export PATH
function parse_git_dirty {
[[ $(git status 2> /dev/null | tail -n1) != "nothing to commit (working directory clean)" ]] && echo "*"
}
function parse_git_branch {
git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e "s/* \(.*\)/[\1$(parse_git_dirty)]/"
}
PATH=$PATH:/usr/local/rvm/bin # Add RVM to PATH for scripting
### Added by the Heroku Toolbelt
Or maybe the bash_profile?
if [ -f ~/.bashrc ]; then
   source ~/.bashrc
fi
[[ -s "/usr/local/rvm/scripts/rvm" ]] && source "/usr/local/rvm/scripts/rvm" # Load RVM into a shell session *as a function*
Any thoughts are helpful.
Things to check - as suggested above:
anything changed recently? if so, start there... (added new line/command/sourced file?)
look for 'control codes' in the your file(s)
Try:
cat -v ~/.bashrc ## look for '^M' or other special chars - remove if present
bash -n ~/.bashrc ## try the 'sourced files' separately
If using VI, some thing to try after opening the file:
:syntax off ## turn off colors - may be easier to see 'hidden' codes
:set list ## control codes may be visible

Cron job does NOT get the environment variables set in .bashrc

Here is my cron job:
plee#dragon:~$ crontab -l
* * * * * /bin/bash -l -c 'source ~/.bashrc; echo $EDITOR > /tmp/cronjob.test'
and inside ~/.bashrc file, I have export EDITOR=vim, but in the final /tmp/cronjob.test file, it's still empty?
So how can I get the environment variables (set in .bashrc file) and use it in my cron job?
plee#dragon:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 12.04 LTS
Release: 12.04
Codename: precise
plee#dragon:~$ uname -a
Linux dragon 3.2.0-26-generic-pae #41-Ubuntu SMP Thu Jun 14 16:45:14 UTC 2012 i686 i686 i386 GNU/Linux
If use this:
* * * * * /bin/bash -l -c -x 'source ~/.bashrc; echo $EDITOR > /tmp/cronjob.test' 2> /tmp/cron.debug.res
In /tmp/cron.debug.res:
...
++ return 0
+ source /home/plee/.bashrc
++ '[' -z '' ']'
++ return
+ echo
BTW, the .bashrc file is the default one came with Ubuntu 12.04, with the exception that I added one line export EDITOR=vim.
If I don't use the cron job, instead, just directly do this on the command line:
source .bashrc; echo $EDITOR # Output: vim
The reason for source ~/.bashrc not working is the contents on your ~/.bashrc (default one from Ubuntu 12.04). If you look in it you will see on lines 5 and 6 the following:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
PS1 variable is set for an interactive shell, so it's absent when run via cron, even though you are executing it as a login shell. This is confirmed by contents of the file produced by /bin/bash -l -c -x 'source ~/.bashrc; echo $EDITOR > /tmp/cronjob.test':
+ source /home/plee/.bashrc
++ '[' -z '' ']'
++ return
To make source ~/.bashrc work, comment out the line that checks for presence of the PS1 variable in ~/.bashrc:
#[ -z "$PS1" ] && return
This will make bash execute the entire contents of ~/.bashrc via cron
Answer provided by #alex is correct but in Ubuntu 13.10 the code has been modified a little. There is no $PS1 variable but in lines 6-9 there is a code
case $- in
*i*) ;;
*) return;;
esac
Just commenting out the line which returns works. i.e. the code below works
case $- in
*i*) ;;
# *) return;;
esac
I just tried a file .env_setup_rc file with only one line export EDITOR=vim, surprisingly it's working.
So I guess there is something in .bashrc conflicting with the cron job bash command.

Resources