182

I'm trying to write (what I thought would be) a simple bash script that will:

  1. run virtualenv to create a new environment at $1
  2. activate the virtual environment
  3. do some more stuff (install django, add django-admin.py to the virtualenv's path, etc.)

Step 1 works quite well, but I can't seem to activate the virtualenv. For those not familiar with virtualenv, it creates an activate file that activates the virtual environment. From the CLI, you run it using source

source $env_name/bin/activate

Where $env_name, obviously, is the name of the dir that the virtual env is installed in.

In my script, after creating the virtual environment, I store the path to the activate script like this:

activate="`pwd`/$ENV_NAME/bin/activate"

But when I call source "$activate", I get this:

/home/clawlor/bin/scripts/djangoenv: 20: source: not found

I know that $activate contains the correct path to the activate script, in fact I even test that a file is there before I call source. But source itself can't seem to find it. I've also tried running all of the steps manually in the CLI, where everything works fine.

In my research I found this script, which is similar to what I want but is also doing a lot of other things that I don't need, like storing all of the virtual environments in a ~/.virtualenv directory (or whatever is in $WORKON_HOME). But it seems to me that he is creating the path to activate, and calling source "$activate" in basically the same way I am.

Here is the script in its entirety:

#!/bin/sh

PYTHON_PATH=~/bin/python-2.6.1/bin/python

if [ $# = 1 ]
then
    ENV_NAME="$1"
    virtualenv -p $PYTHON_PATH --no-site-packages $ENV_NAME
    activate="`pwd`/$ENV_NAME/bin/activate"

    if [ ! -f "$activate" ]
    then
        echo "ERROR: activate not found at $activate"
        return 1
    fi

    source "$activate"
else
    echo 'Usage: djangoenv ENV_NAME'
fi

DISCLAIMER: My bash script-fu is pretty weak. I'm fairly comfortable at the CLI, but there may well be some extremely stupid reason this isn't working.

5 Answers 5

250

If you're writing a bash script, call it by name:

#!/bin/bash

/bin/sh is not guaranteed to be bash. This caused a ton of broken scripts in Ubuntu some years ago (IIRC).

The source builtin works just fine in bash; but you might as well just use dot like Norman suggested.

Sign up to request clarification or add additional context in comments.

2 Comments

This solution was originally a comment in Norman Ramsey's answer. Since this is what actually fixed the problem, I've changed this to be the 'accepted answer'
So, how do you call bash by name if you were just typing source ~/.bashrc before? Do you do bash ~/.bashrc?
227

In the POSIX standard, which /bin/sh is supposed to respect, the command is . (a single dot), not source. The source command is a csh-ism that has been pulled into bash.

Try

. $env_name/bin/activate

Or if you must have non-POSIX bash-isms in your code, use #!/bin/bash.

5 Comments

That fixes it. (changing /bin/sh to /bin/bash). For some reason the environment is not activated in the CLI when the script finishes, but that's a minor problem.
According to the Bash manual source is a synonym for ..
I came across this when using a docker container with entrypoint like this, /bin/sh -c '/path/to/script.sh'. Even though my script was a bash script, source failed to source the exports. But "." worked!
This fixed it for me - testing my .sh in the shell was working with source, but failing in Jenkins. Changing source to a dot worked in the shell and most importantly, worked in Jenkins too. Thanks!
As @NikhilOwalekar I also came across this during containerisation, albeit with Apptainer/Singularity. Using "." instead of "source" worked for me as well.
38

In Ubuntu if you execute the script with sh scriptname.sh you get this problem.

Try executing the script with ./scriptname.sh instead.

3 Comments

i got a segmentation fault when doing this.
File must be executable: chmod +x filename.sh
Any idea why this is?
1

best to add the full path of the file you intend to source.

eg

source ./.env instead of source .env

or source /var/www/html/site1/.env

Comments

0

After multiple attempts I found below. Simply do

$ ./env_name/bin/activate

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.