Bash – How to source the .bashrc from a shell script

bash

I have a bash script script.sh which contains the following line:

sudo -u myusername sh ~/.profile

From a shell I am able to just call source ~/.profile but that does not work in a script and this command does. It forces my current shell to read my ~/.profile

However, my ~/.profile contains the following lines:

if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

As it is supposed to source my ~/.bashrc. But, when I run script.sh I get the following error:

/home/username/.profile: 24: /home/username/.profile: source: not found

Is it possible to source my ~/.bashrc file from my ~/.profile (which is itself being called from another script) without changing either my ~/.bashrc or my ~/.profile?

This script.sh downloads my ~/.profile and ~/.bashrc file and puts them in the right place, so I want to source those files from within script.sh once they are downloaded and have them affect the shell session which I used to run script.sh

Best Answer

The error comes from trying to execute the ~/.profile file with sh, which does not understand source (sh uses . (dot) instead, which also works in bash and all other POSIX shells).

Furthermore, executing ~/.profile will not set the environment variables that this file sets in the shell that executes it. This is because it runs in its own subshell.

A child shell (which is what you get when you execute ~/.profile rather than sourcing it) will never affect the environment of the parent shell (the shell that you execute the script from). You can therefore not set variables in ~/.profile and expect them to then be set in your script unless you source the file.

Running sudo source ~/.profile will not help here as sudo will be a child process of the current shell.


Related, extra information:

To set up the environment for a script that is not run from an interactive shell (where ~/.profile and ~/.bashrc are already sourced), set the BASH_ENV variable to the appropriate file upon invoking the script. This will make bash source the $BASH_ENV file before handing control over to your script.

For example:

BASH_ENV="$HOME/.profile" "$HOME/scripts/myscript.sh"

This is only necessary if invoking the script from a non-interactive shell session, such as a cron job, and if you need to access environment variables set up in ~/.profile or any file that ~/.profile sources.

From an interactive shell session, the BASH_ENV variable does not have to be set in this way, and the script does not need to source ~/.bashrc nor ~/.profile since these have already been sourced.

Related Question