我有一台 Linux 服务器和一台 Linux 桌面。
我编写了以下简单脚本来转储 django web 应用程序的数据库:
#! /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
更改了 shell 路径。/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 路径上获取它?
答案1
修改你的脚本并放在-l
shebang后面。#!/bin/bash -l
或者将您的 ssh 命令更改为ssh HOSTNAME bash -l /var/www/example.com/dumper.sh
原因:当您运行ssh HOSTNAME command
而不是仅仅 时ssh HOSTNAME
,用于启动的 shellcommand
不是“登录”shell,因此会调用不同的脚本(请参阅 的 INVOCATION 部分man bash
),这会导致您的环境设置不同。
答案2
我发现您需要引用 bash 行才能正确识别 -l,如下所示:
ssh 主机名 "bash -l /path/to/script.sh"
答案3
在一行中通过 ssh 运行 cmd 时,不会读取 .profile。要进行测试,请尝试以下操作:
ssh host env
请使用这个来修复这个问题(必须加引号):
ssh host '. ~/.profile; cmd'
例如:
ssh HOSTNAME '. ~/.bashrc; /var/www/example.com/dumper.sh'