ChatGPT解决这个技术问题 Extra ChatGPT

Getting a 'source: not found' error when using source in a bash script

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

run virtualenv to create a new environment at $1 activate the virtual environment 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 it's 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.


g
guns

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.


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?
N
Norman Ramsey

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.


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!
A
Addison

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

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


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