174

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.

danronmoon
  • 3,814
  • 5
  • 34
  • 56
Chris Lawlor
  • 47,306
  • 11
  • 48
  • 68

5 Answers5

247

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.

guns
  • 10,550
  • 3
  • 39
  • 36
  • 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' – Chris Lawlor Dec 17 '09 at 22:20
  • So, how do you call bash by name if you were just typing `source ~/.bashrc` before? Do you do `bash ~/.bashrc`? – Brōtsyorfuzthrāx Sep 16 '21 at 20:14
217

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.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 1
    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. – Chris Lawlor Mar 22 '09 at 00:29
  • 10
    According to the [Bash manual](https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#index-source) `source` is a synonym for `.`. – Richard Hansen Nov 11 '15 at 06:00
  • 1
    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! – Nikhil Owalekar Sep 26 '18 at 10:31
  • 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! – pa1983 Jun 22 '23 at 10:04
37

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

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

Addison
  • 7,322
  • 2
  • 39
  • 55
Madhu
  • 371
  • 3
  • 2
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

mikoop
  • 1,981
  • 1
  • 18
  • 18
0

After multiple attempts I found below. Simply do

$ ./env_name/bin/activate

viraj ghorpade
  • 473
  • 5
  • 8