У меня есть сервер Linux и рабочий стол Linux.
Я написал следующий простой скрипт для дампа базы данных веб-приложения django:
#! /bin/bash
set -o errexit
cd $(dirname $0)
. virtualenv/bin/activate
cd mysite
export DJANGO_SETTINGS_MODULE="settings.my_hostname"
django-admin.py dumpdata --settings=$DJANGO_SETTINGS_MODULE > database.json
Программа django-admin.py
требует DJANGO_SETTINGS_MODULE
переменная среды для правильной работы.
Если я подключусь к машине по ssh, ssh HOSTNAME
, а затем запустите сценарий /var/www/example.com/dumper.sh
с терминала bash на удаленном хосте, и все работает нормально. Я не получаю вывода (как и ожидалось), а файл database.json
есть и имеет нужные данные.
Однако (на моем рабочем столе Linux) я не могу запустить эту команду: «ssh HOSTNAME / var / www / example.com / dumper.sh», и я получаю следующую ошибку:
Traceback (most recent call last):
File "/var/www/example.com/virtualenv/bin/django-admin.py", line 5, in <module>
management.execute_from_command_line()
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/core/management/__init__.py", line 429, in execute_from_command_line
utility.execute()
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/core/management/__init__.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/core/management/__init__.py", line 261, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/core/management/__init__.py", line 67, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/core/management/commands/dumpdata.py", line 4, in <module>
from django.db import connections, router, DEFAULT_DB_ALIAS
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/db/__init__.py", line 14, in <module>
if not settings.DATABASES:
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/utils/functional.py", line 276, in __getattr__
self._setup()
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/conf/__init__.py", line 42, in _setup
self._wrapped = Settings(settings_module)
File "/var/www/example.com/virtualenv/lib/python2.6/site-packages/django/conf/__init__.py", line 89, in __init__
raise ImportError("Could not import settings '%s' (Is it on sys.path?): %s" % (self.SETTINGS_MODULE, e))
ImportError: Could not import settings 'settings.my_hostname' (Is it on sys.path?): No module named settings.my_hostname
Как будто export
команда не выполняется или не действует.
Почему это не работает? (Или альтернативно должен это работает? Я ошибаюсь, думая, что это должно работать?)
По предложению @faker я поставил echo $PATH
в скрипте перед вызовом django-admin.py
. В . virtualenv/bin/activate
изменяет путь к оболочке. Я получаю путь /var/www/example.com/virtualenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games
когда я запускаю его через ssh HOSTNAME /path/to/script.sh
, и после входа я получаю /var/www/example.com/virtualenv/bin:/home/rory/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games
. Единственная разница - это ~/bin
часть, но я сделал which django-admin.py
а также, и в обоих случаях он использует /var/www/example.com/virtualenv/bin/django-admin.py
поэтому в обоих случаях используется одна и та же программа для django-admin.py
команда.
По совету @Andrew Schulman того же самого, но для $PYTHONPATH
. PYTHONPATH был пуст в обоих случаях. Однако я добавил python -c 'import sys; print sys.path'
вместо просто echo $PYTHONPATH
, и получил разные результаты.
Когда я ssh в HOSTNAME и запускаю скрипт вручную (тот, который работает):
['', '/var/www/example.com/virtualenv/lib/python2.6/site-packages/distribute-0.6.10-py2.6.egg', '/var/www/example.com/virtualenv/lib/python2.6/site-packages/pip-1.0.2-py2.6.egg', '/var/www/example.com/mysite', '/home/rory/code/python/lib', '/var/www/example.com/virtualenv/lib/python2.6', '/var/www/example.com/virtualenv/lib/python2.6/plat-linux2', '/var/www/example.com/virtualenv/lib/python2.6/lib-tk', '/var/www/example.com/virtualenv/lib/python2.6/lib-old', '/var/www/example.com/virtualenv/lib/python2.6/lib-dynload', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/var/www/example.com/virtualenv/lib/python2.6/site-packages']
Когда я вызываю скрипт по ssh (это не работает):
['', '/var/www/example.com/virtualenv/lib/python2.6/site-packages/distribute-0.6.10-py2.6.egg', '/var/www/example.com/virtualenv/lib/python2.6/site-packages/pip-1.0.2-py2.6.egg', '/var/www/example.com/virtualenv/lib/python2.6', '/var/www/example.com/virtualenv/lib/python2.6/plat-linux2', '/var/www/example.com/virtualenv/lib/python2.6/lib-tk', '/var/www/example.com/virtualenv/lib/python2.6/lib-old', '/var/www/example.com/virtualenv/lib/python2.6/lib-dynload', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/var/www/example.com/virtualenv/lib/python2.6/site-packages']
В рабочей версии есть /var/www/example.com/mysite
. Файл настроек находится в /var/www/example.com/mysite/settings/my_hostname.py
. Это имеет смысл, поскольку рабочий вызов может загрузить файл.
Почему "удаленно вызываемая" версия не получает это на своем пути Python?
Измените свой скрипт и поставьте -l
после шебанга. так #!/bin/bash -l
В качестве альтернативы измените свою команду ssh на ssh HOSTNAME bash -l /var/www/example.com/dumper.sh
Обоснование: когда вы бежите ssh HOSTNAME command
вместо просто ssh HOSTNAME
, оболочка, используемая для запуска command
не является оболочкой для входа в систему, поэтому вызываются разные сценарии (см. раздел ВЫЗОВ man bash
), в результате чего ваша среда будет настроена иначе.
При запуске cmd поверх ssh в одну строку .profile не читается. Чтобы проверить, попробуйте это:
ssh host env
Используйте это вместо этого, чтобы исправить эту проблему (кавычки являются обязательными):
ssh host '. ~/.profile; cmd'
например:
ssh HOSTNAME '. ~/.bashrc; /var/www/example.com/dumper.sh'
Я обнаружил, что вам нужно процитировать строку bash, чтобы она правильно распознала -l, например:
ssh ИМЯ ХОСТА "bash -l /path/to/script.sh"