3 votes

Je peux exécuter un script localement, mais je ne peux pas faire "ssh HOSTNAME /path/to/script.sh"

J'ai un serveur linux et un ordinateur de bureau linux.

J'ai écrit le simple script suivant pour vider la base de données d'une application web 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

Le programme django-admin.py exige que le DJANGO_SETTINGS_MODULE pour fonctionner correctement.

Si je me connecte à la machine, ssh HOSTNAME puis exécutez le script. /var/www/example.com/dumper.sh depuis le terminal bash de l'hôte distant, et tout fonctionne correctement. Je n'obtiens aucune sortie (comme prévu), et le fichier database.json est là et possède les bonnes données.

Cependant (sur mon ordinateur de bureau linux), je ne peux pas exécuter cette commande : "ssh HOSTNAME /var/www/example.com/dumper.sh" et j'obtiens l'erreur suivante :

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

C'est comme si le export n'est pas exécutée ou n'a pas d'effet.

Pourquoi cela ne fonctionne-t-il pas ? (Ou alternativement devrait cela fonctionne-t-il ? Est-ce que je me trompe en pensant que cela devrait fonctionner ?)

Mise à jour 1

Sur la suggestion de @faker, j'ai mis echo $PATH dans le script avant l'appel à django-admin.py . En . virtualenv/bin/activate modifie le chemin d'accès à Shell. J'obtiens un chemin de /var/www/example.com/virtualenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games lorsque je l'exécute via ssh HOSTNAME /path/to/script.sh et après m'être connecté, j'obtiens /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 . La seule différence est le ~/bin mais j'ai fait une which django-admin.py également, et dans les deux cas, il utilise /var/www/example.com/virtualenv/bin/django-admin.py Ainsi, dans les deux cas, il utilise le même programme pour la django-admin.py commande.

Mise à jour 2

Sur le conseil de @Andrew Schulman, la même chose, mais pour $PYTHONPATH . PYTHONPATH était vide dans les deux cas. Cependant, j'ai ajouté python -c 'import sys; print sys.path' au lieu de echo $PYTHONPATH et ont obtenu des résultats différents.

Lorsque je me connecte à HOSTNAME et que j'exécute script manuellement (celui qui fonctionne) :

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

Lorsque j'invoque le script via ssh (cela ne fonctionne pas) :

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

La version de travail comporte un /var/www/example.com/mysite . Le fichier de configuration est situé dans /var/www/example.com/mysite/settings/my_hostname.py . Cela est logique puisque l'invokcation de travail peut charger le fichier.

Pourquoi la version "invoquée à distance" ne l'obtient-elle pas sur son chemin Python ?

2voto

Andriyev Points 9238

Modifiez votre script et mettez -l après le tout. #!/bin/bash -l

Vous pouvez également modifier votre commande ssh en ssh HOSTNAME bash -l /var/www/example.com/dumper.sh

Raison d'être : Lorsque vous exécutez ssh HOSTNAME command au lieu de ssh HOSTNAME Le Shell utilisé pour lancer l'application command n'est pas un Shell de "connexion", et donc différents Shell sont appelés (Voir la section INVOCATION de man bash ), ce qui entraîne une configuration différente de votre environnement.

1voto

Mike S Points 1033

J'ai découvert qu'il faut citer la ligne bash pour qu'elle reconnaisse correctement le -l, comme ceci :

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

1voto

sp1111 Points 111

Lors de l'exécution de cmd over ssh en une seule ligne, le .profile n'est pas lu. Pour tester, essayez ceci :

ssh host env

Utilisez plutôt ceci pour résoudre ce problème (les guillemets sont obligatoires) :

ssh host '. ~/.profile; cmd'

eg :

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

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X