我可以在本地运行脚本,但无法执行“ssh HOSTNAME /path/to/script.sh”

我可以在本地运行脚本,但无法执行“ssh HOSTNAME /path/to/script.sh”

我有一台 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

修改你的脚本并放在-lshebang后面。#!/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'

相关内容