3

I have a linux server, and a linux desktop.

I have written the following simple script to dump the database of a django web application:

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

The programme django-admin.py requires the DJANGO_SETTINGS_MODULE environmental variable to work properly.

If I ssh into the machine, ssh HOSTNAME, and then run the script /var/www/example.com/dumper.sh from the bash terminal on the remote host, and everything works fine. I get no output (as expected), and the file database.json is there and has the right data.

However (on my linux desktop), I cannot run this command: "ssh HOSTNAME /var/www/example.com/dumper.sh`` and I get the following error:

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

It's as if the export command isn't being run, or isn't taking effect.

Why doesn't this work? (Or alternatively should it work? Am I mistaken in thinking that this should work?)

Update №1

On @faker's suggestion, I put echo $PATH in the script before the call to django-admin.py. The . virtualenv/bin/activate changes the shell path. I get a path of /var/www/example.com/virtualenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games when I run it via ssh HOSTNAME /path/to/script.sh, and after logging in I get /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. The only difference is the ~/bin part, but I did a which django-admin.py aswell, and in both instances it's using /var/www/example.com/virtualenv/bin/django-admin.py so in both instances it's using the same programme for the django-admin.py command.

Update №2

On @Andrew Schulman's advice of the same, but for $PYTHONPATH. PYTHONPATH was empty in both cases. However I added python -c 'import sys; print sys.path' instead of just echo $PYTHONPATH, and got different results.

When I ssh into HOSTNAME and run script manually (the one that works):

['', '/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']

When I invoke the script over ssh (this doesn't work):

['', '/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']

The working version has a /var/www/example.com/mysite. The settings file is located in /var/www/example.com/mysite/settings/my_hostname.py. This makes sense since the working invokcation can load the file.

Why isn't the 'remotely invoked' version getting that on it's python path?

2
  • 2
    Try ssh HOSTNAME "echo $PATH" and compare it with echo $PATH from a shell where running django-admin.py works. Is it different?
    – faker
    Nov 3, 2011 at 22:42
  • 1
    Do the same as above with $PYTHONPATH. Note the message from Python on the last line: Could not import settings 'settings.my_hostname' (Is it on sys.path?) Nov 4, 2011 at 10:26

3 Answers 3

2

Change your script and put -l after the shebang. so #!/bin/bash -l

Alternatively change your ssh command to ssh HOSTNAME bash -l /var/www/example.com/dumper.sh

Rationale: When you run ssh HOSTNAME command instead of just ssh HOSTNAME, the shell used to launch command is not a 'login' shell, and so different scripts get called (See the INVOCATION section of man bash) which results in your environment being setup differently.

3
  • Tried that, but it didn't work. I got the same output if I put a -l in the shebang line, or used ssh HOSTNAME -l … Nov 4, 2011 at 10:12
  • No, ssh HOSTNAME bash -l ..., you need to put the 'bash' there
    – phemmer
    Nov 5, 2011 at 4:31
  • I mistyped. I used ssh HOSTNAME bash -l /path/to/script.sh and it didn't work. Nov 5, 2011 at 16:54
1

I have discovered that you need to quote the bash line for it to recognize the -l properly, like this:

ssh HOSTNAME "bash -l /path/to/script.sh"

1

When running cmd over ssh in one line, the .profile is not read. To test, try this:

ssh host env

Use this instead to fix this issue (quotes are compulsory):

ssh host '. ~/.profile; cmd'

eg:

ssh HOSTNAME '. ~/.bashrc; /var/www/example.com/dumper.sh'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.