daveoncode daveoncode - 7 months ago 32
Bash Question

Reloading environment variables inside a bash script

I'm writing a series of Ubuntu post-install scripts in order to install libraries and tools I need, one of this should install pyenv and latest python version using the former, the script is the following:

#!/usr/bin/env bash

# clone the github repo
echo "Installing pyenv..."
git clone https://github.com/yyuu/pyenv.git ~/.pyenv

# update .bashrc
echo '# pyenv settings:' >> ~/.bashrc
echo 'export PYENV_ROOT="~/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'export PATH="~/.pyenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc

# reload
. ~/.bashrc

# install python and virtualenv
echo "Installing python 3.5.1 + virtualenv..."
pyenv install 3.5.1
pyenv global 3.5.1
pip install --upgrade pip
pip install virtualenv
echo "pyenv has been installed with python 3.5.1 and virtualenv"


The problem is that the reload (
. ~/.bashrc
) seems to not work as expected,because I get:

python.sh: pyenv: not found
python.sh: pip: not found


I also tried with
source ~/.bashrc
and
exec $SHELL
but the problem remains.

How can I solve the problem?

ps: I'm executing the script with:
sudo sh python.sh

Answer

If ~ is quoted, it does not expand to the user's home directory. Use this instead.

echo '# pyenv settings:' >> ~/.bashrc
echo 'export PYENV_ROOT=~/.pyenv' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'export PATH=~/.pyenv/bin:"$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc

I would also rewrite it to look something like this:

cat <<'EOF' >> ~/.bashrc
# pyenv settings:
export PYENV_ROOT=~/.pyenv
export PATH=$PYENV_ROOT/bin:$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
EOF

However, you shouldn't be sourcing the user's .bashrc file; you don't know what else is in there, and you don't need to execute the whole thing, just the parts needed for the rest of your script. Replace . ~/.bashrc with

export PYENV_ROOT=~/.pyenv
export PATH=$PYENV_ROOT/bin:$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"