Назад | Перейти на главную страницу

Я могу запустить сценарий локально, но не могу выполнить «ssh HOSTNAME /path/to/script.sh»

У меня есть сервер 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 команда не выполняется или не действует.

Почему это не работает? (Или альтернативно должен это работает? Я ошибаюсь, думая, что это должно работать?)

Обновление №1

По предложению @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 команда.

Обновление №2

По совету @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"