Получение ошибки «источник: не найден» при использовании источника в bash-скрипте

159

Я пытаюсь написать (как я думал, будет) простой скрипт bash, который будет:

  1. запустить virtualenv, чтобы создать новую среду за 1 доллар
  2. активировать виртуальную среду
  3. сделать еще кое-что (установить django, добавить django-admin.py к пути в virtualenv и т. д.)

Шаг 1 работает довольно хорошо, но я не могу активировать virtualenv. Для тех, кто не знаком с virtualenv, он создает activateфайл, который активирует виртуальную среду. Из CLI вы запускаете его, используяsource

source $env_name/bin/activate

Где $ env_name, очевидно, является именем директории, в которой установлен виртуальный env.

В моем сценарии после создания виртуальной среды я сохраняю путь к сценарию активации следующим образом:

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

Но когда я звоню source "$activate", я получаю это:

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

Я знаю, что он $activateсодержит правильный путь к скрипту активации, на самом деле я даже проверяю, есть ли файл перед вызовом source. Но sourceсам не могу найти его. Я также попытался выполнить все шаги вручную в CLI, где все работает нормально.

В своем исследовании я нашел этот сценарий , который похож на то, что я хочу, но также выполняет много других вещей, которые мне не нужны, например, хранение всех виртуальных сред в каталоге ~ / .virtualenv (или в любом другом месте). $ WORKON_HOME). Но мне кажется, что он создает путь activateи призывает source "$activate"в основном так же, как я.

Вот сценарий целиком:

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

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Мой сценарий bash довольно слаб. Мне довольно удобно в CLI, но вполне может быть какая-то чрезвычайно глупая причина, по которой это не работает.

Крис Лоулор
источник

Ответы:

230

Если вы пишете скрипт bash, называйте его по имени:

#!/bin/bash

/ bin / sh не обязательно будет bash. Это вызвало множество сломанных скриптов в Ubuntu несколько лет назад (IIRC).

Встроенная программа-источник прекрасно работает в bash; но вы могли бы просто использовать точку, как предложил Норман.

оружие
источник
Это решение изначально было комментарием в ответе Нормана Рэмси. Поскольку это то, что на самом деле решило проблему, я изменил это на «принятый ответ»
Крис Лоулор
186

В стандарте POSIX, который /bin/shдолжен соблюдаться, команда .(одна точка), а не source. Команда source- это csh-изм, который был введен bash.

Пытаться

. $env_name/bin/activate

Или, если bashв вашем коде должны быть не-POSIX -измы, используйте #!/bin/bash.

Норман Рэмси
источник
1
Это исправляет это. (изменение / bin / sh на / bin / bash). По какой-то причине среда не активируется в CLI, когда сценарий завершается, но это небольшая проблема.
Крис Лоулор
8
Согласно Bash руководство source является синонимом ..
Ричард Хансен
1
Я наткнулся на это при использовании Docker контейнера с EntryPoint , как это, /bin/sh -c '/path/to/script.sh'. Несмотря на то, что мой сценарий был сценарием bash, источник не смог экспортировать экспорт. Но "." работал!
Нихил Овалекар
31

В Ubuntu, если вы выполняете скрипт вместе с sh scriptname.shвами, возникает эта проблема.

Попробуйте ./scriptname.shвместо этого выполнить скрипт .

Мадху
источник
я получил ошибку сегментации при этом.
Макс Плинер
1
Файл должен быть исполняемым:chmod +x filename.sh
Рэнди
2
Есть идеи, почему это так?
Ювал Адам
Единственное, что сработало для моего Ubuntu 20.04
Кирилл_Зайцев