Pojawia się błąd „source: not found” podczas używania źródła w skrypcie bash

159

Próbuję napisać (tak mi się wydawało) prosty skrypt bash, który:

  1. uruchom virtualenv, aby utworzyć nowe środowisko za 1 USD
  2. aktywuj środowisko wirtualne
  3. zrób więcej rzeczy (zainstaluj django, dodaj django-admin.py do ścieżki virtualenv itp.)

Krok 1 działa całkiem dobrze, ale nie mogę aktywować virtualenv. Dla tych, którzy nie są zaznajomieni z virtualenv, tworzy activateplik, który aktywuje wirtualne środowisko. Z CLI uruchamiasz go za pomocąsource

source $env_name/bin/activate

Gdzie $ env_name, oczywiście, jest nazwą katalogu, w którym wirtualne env jest zainstalowane.

W moim skrypcie po utworzeniu środowiska wirtualnego przechowuję ścieżkę do skryptu aktywacyjnego w następujący sposób:

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

Ale kiedy dzwonię source "$activate", dostaję to:

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

Wiem, że $activatezawiera poprawną ścieżkę do skryptu aktywacji, w rzeczywistości nawet sprawdzam, czy plik jest tam, zanim zadzwonię source. Ale sourcewydaje się, że sam nie może tego znaleźć. Próbowałem też uruchomić wszystkie kroki ręcznie w CLI, gdzie wszystko działa dobrze.

W swoich badaniach znalazłem ten skrypt , który jest podobny do tego, co chcę, ale robi również wiele innych rzeczy, których nie potrzebuję, takich jak przechowywanie wszystkich środowisk wirtualnych w katalogu ~ / .virtualenv (lub czymkolwiek jest w $ WORKON_HOME). Ale wydaje mi się, że tworzy ścieżkę activatei woła source "$activate"w zasadzie tak samo jak ja.

Oto cały skrypt:

#!/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

ZRZECZENIE SIĘ: Mój skrypt-fu bash jest dość słaby. Czuję się dość dobrze w CLI, ale może być jakiś wyjątkowo głupi powód, dla którego to nie działa.

Chris Lawlor
źródło

Odpowiedzi:

230

Jeśli piszesz skrypt basha, nazwij go po imieniu:

#!/bin/bash

Nie ma gwarancji, że / bin / sh będzie bash. Spowodowało to mnóstwo zepsutych skryptów w Ubuntu kilka lat temu (IIRC).

Wbudowane źródło działa dobrze w bash; ale równie dobrze możesz po prostu użyć kropki, jak sugerował Norman.

pistolety
źródło
To rozwiązanie było pierwotnie komentarzem w odpowiedzi Normana Ramseya. Ponieważ to właśnie rozwiązało problem, zmieniłem to na „zaakceptowaną odpowiedź”
Chris Lawlor,
185

W standardzie POSIX, który /bin/shma przestrzegać, polecenie to .(pojedyncza kropka), a nie source. To sourcepolecenie jest csh-izmem, w który został wciągnięty bash.

Próbować

. $env_name/bin/activate

Lub jeśli musisz mieć bashw swoim kodzie -izmy inne niż POSIX , użyj #!/bin/bash.

Norman Ramsey
źródło
1
To rozwiązuje problem. (zmiana / bin / sh na / bin / bash). Z jakiegoś powodu środowisko nie jest aktywowane w CLI po zakończeniu działania skryptu, ale to drobny problem.
Chris Lawlor,
8
Według instrukcji Bash source jest synonimem ..
Richard Hansen
1
Natknąłem się na to podczas korzystania z pojemnika Döcker punkt_wejścia jak ta /bin/sh -c '/path/to/script.sh'. Mimo że mój skrypt był skryptem bash, źródło nie mogło pobrać eksportu. Ale "." zadziałało!
Nikhil Owalekar
31

W Ubuntu, jeśli wykonasz skrypt za pomocą sh scriptname.sh, pojawi się ten problem.

./scriptname.shZamiast tego spróbuj wykonać skrypt za pomocą .

Madhu
źródło
mam błąd segmentacji podczas wykonywania tej czynności.
max pleaner
1
Plik musi być wykonywalny:chmod +x filename.sh
Randy
2
Masz jakiś pomysł, dlaczego tak jest?
Yuval Adam
Jedyna rzecz, która działała na moim Ubuntu 20.04
Kirill_Zaitsev