Herstellen einer Verbindung zu einem in ~ / .ssh / config aufgelisteten Host bei Verwendung von Fabric

83

Ich habe Probleme damit Fabric, Hosts, in denen ich mich befinde, nicht zu erkennen ~/.ssh/config.

Mein fabfile.pyist wie folgt:

from fabric.api import run, env

env.hosts = ['lulu']

def whoami():
    run('whoami')

Laufen $ fab whoamigibt:

[lulu] rennen: whoami

Schwerwiegender Fehler: Namenssuche für Lulu fehlgeschlagen

Der Name luluist in meinem ~/.ssh/config, so:

Host lulu
     hostname 192.168.100.100
     port 2100
     IdentityFile ~/.ssh/lulu-key

Mein erster Gedanke, um dies zu lösen, ist das Hinzufügen lulu.luluvon /etc/hosts(ich bin auf einem Mac), aber dann muss ich auch die Identitätsdatei an Fabric übergeben - und ich möchte lieber meine Authentifizierung (dh ~/.ssh/config) von meiner Bereitstellung trennen ( dh fabfile.py).

Übrigens, wenn Sie versuchen, eine Verbindung zu einem Host in der Hosts-Datei herzustellen, werden fabric.contrib.projects.rsync_project'Ports' in der Datei übrigens nicht bestätigt hosts.env(dh wenn Sie hosts.env = [lulu:2100]einen Anruf verwenden, um rsync_projectzu versuchen, eine Verbindung herzustellen lulu:21).

Gibt es einen Grund, warum Fabric diesen luluNamen nicht erkennt ?

Brian M. Hunt
quelle

Antworten:

145

Seit Version 1.4.0 verwendet Fabric (teilweise) Ihre ssh-Konfiguration . Sie müssen es jedoch explizit mit aktivieren

env.use_ssh_config = True

Irgendwo in der Nähe der Spitze Ihres Fabfiles. Sobald Sie dies getan haben, sollte Fabric Ihre SSH-Konfiguration lesen ( ~/.ssh/configstandardmäßig von oder von env.ssh_config_path).

Eine Warnung: Wenn Sie eine Version verwenden, die älter als 1.5.4 ist, tritt ein Abbruch auf, wenn env.use_ssh_configfestgelegt, aber keine Konfigurationsdatei vorhanden ist. In diesem Fall können Sie eine Problemumgehung wie folgt verwenden:

if env.ssh_config_path and os.path.isfile(os.path.expanduser(env.ssh_config_path)):
    env.use_ssh_config = True
rbp
quelle
Die Antwort begann ursprünglich mit "Die akzeptierte Antwort ist veraltet" [da das Verhalten vor 1.4.0 dokumentiert wurde]. Ich habe dieses Vorwort entfernt, da meine Antwort stattdessen akzeptiert wurde;) Danke!
rbp
9

Beachten Sie, dass dies auch passiert, wenn der Name nicht vorhanden ist /etc/hosts. Ich hatte das gleiche Problem und musste den Hostnamen sowohl zu dieser Datei als auch zu dieser Datei hinzufügen ~/.ssh/config.

MrD
quelle
5

Update : Diese Antwort ist jetzt veraltet .


Fabric unterstützt die .ssh / config-Datei derzeit nicht. Sie können diese in einer Funktion einrichten, um dann die CLI aufzurufen, z. B.: Fab Production Task; Dabei legt die Produktion den Benutzernamen, den Hostnamen, den Port und die SSH-Identität fest.

Was das rsync-Projekt betrifft, sollte es jetzt über die Fähigkeit zur Porteinstellung verfügen. Wenn nicht, können Sie immer lokal ("rsync ...") ausführen, da dies im Wesentlichen die Funktion dieser beitragenden Funktion ist.

Morgan
quelle
1
Setzen Sie env.key_filename auf den vollständigen Pfad des privaten Schlüssels. Auch wenn Sie auf Probleme stoßen , finden Sie unter code.fabfile.org/issues/show/265 einige Probleme.
Tobych
1
Ja, es hat jetzt Unterstützung. (obwohl es vor 1.0 war, als ich kommentierte) Hinweis für spätere Leser.
Morgan
4

Zum Lesen der Konfiguration kann folgender Code verwendet werden (Originalcode aus: http://markpasc.typepad.com/blog/2010/04/loading-ssh-config-settings-for-fabric.html ):

from fabric.api import *
env.hosts = ['servername']

def _annotate_hosts_with_ssh_config_info():
    from os.path import expanduser
    from paramiko.config import SSHConfig

    def hostinfo(host, config):
        hive = config.lookup(host)
        if 'hostname' in hive:
            host = hive['hostname']
        if 'user' in hive:
            host = '%s@%s' % (hive['user'], host)
        if 'port' in hive:
            host = '%s:%s' % (host, hive['port'])
        return host

    try:
        config_file = file(expanduser('~/.ssh/config'))
    except IOError:
        pass
    else:
        config = SSHConfig()
        config.parse(config_file)
        keys = [config.lookup(host).get('identityfile', None)
            for host in env.hosts]
        env.key_filename = [expanduser(key) for key in keys if key is not None]
        env.hosts = [hostinfo(host, config) for host in env.hosts]

        for role, rolehosts in env.roledefs.items():
            env.roledefs[role] = [hostinfo(host, config) for host in rolehosts]

_annotate_hosts_with_ssh_config_info()
jmu
quelle
1
Fabric 1.2+ verwendet sshBibliothek ( paramikoGabel):try: \n from ssh.config import SSHConfig \n except ImportError: \n from paramiko.config import SSHConfig
JFS
Die SSH-Bibliothek wurde wieder in Paramiko zusammengeführt, z. B.from paramiko.config import SSHConfig
n8henrie