Подключение к хосту, указанному в ~ / .ssh / config при использовании Fabric

83

У меня проблемы с Fabricраспознаванием хостов, которые у меня есть в~/.ssh/config .

Мой fabfile.pyвыглядит следующим образом:

from fabric.api import run, env

env.hosts = ['lulu']

def whoami():
    run('whoami')

Бег $ fab whoamiдает:

[лулу] беги: whoami

Неустранимая ошибка: не удалось найти имя для lulu

Имя luluу меня ~/.ssh/config, вот так:

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

Моя первая мысль к решению этого добавляет что - то вроде lulu.luluк /etc/hosts(я на Mac), но тогда я должен также передать в файл личных данных на ткань - и я предпочел бы сохранить свою идентификацию (то есть ~/.ssh/config) отдельно от моего развертывания ( т.е. fabfile.py).

Также, кстати, если вы пытаетесь подключиться к хосту в файле hosts, fabric.contrib.projects.rsync_projectпохоже , что он не подтверждает «порты» в hosts.env(то есть, если вы используете hosts.env = [lulu:2100]вызов, rsync_projectкажется, пытается подключиться lulu:21).

Есть ли причина, по которой Fabric не распознает это luluимя?

Брайан М. Хант
источник

Ответы:

145

Начиная с версии 1.4.0, Fabric использует вашу конфигурацию ssh (частично). Однако вам нужно явно включить его с помощью

env.use_ssh_config = True

где-то в верхней части вашего fabfile. Как только вы это сделаете, Fabric должна прочитать вашу конфигурацию ssh ( ~/.ssh/configпо умолчанию или из env.ssh_config_path).

Одно предупреждение: если вы используете версию старше 1.5.4, произойдет прерывание, если env.use_ssh_configустановлено, но нет конфигурационного файла. В этом случае вы можете использовать обходной путь, например:

if env.ssh_config_path and os.path.isfile(os.path.expanduser(env.ssh_config_path)):
    env.use_ssh_config = True
rbp
источник
Первоначально ответ начинался со слов «Принятый ответ устарел» [поскольку он документировал поведение до версии 1.4.0]. Я удалил это предисловие, так как вместо этого был принят мой ответ;) Спасибо!
rbp
9

Обратите внимание, что это также происходит, когда имя отсутствует /etc/hosts. У меня была такая же проблема, и мне пришлось добавить имя хоста как в этот файл, так и в ~/.ssh/config.

MrD
источник
5

обновление : этот ответ теперь устарел .


В настоящее время Fabric не поддерживает файл .ssh / config. Вы можете настроить их в функции для последующего вызова cli, например: fab production task; где production устанавливает имя пользователя, имя хоста, порт и идентификатор ssh.

Что касается проекта rsync, у него теперь должна быть возможность настройки порта, если нет, вы всегда можете запустить локальный («rsync ...»), поскольку это, по сути, то, что делает эта дополнительная функция.

Морган
источник
1
В env.key_filename укажите полный путь к закрытому ключу. Также, если у вас возникнут проблемы, см. Code.fabfile.org/issues/show/265 , чтобы узнать о некоторых проблемах, связанных с этим.
tobych
1
Ага, теперь у него есть поддержка. (хотя, когда я комментировал, это была до 1.0) На заметку для последующих читателей.
Morgan
4

Для чтения конфигурации можно использовать следующий код (исходный код взят из: 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
источник
1
fabric 1.2+ использует sshбиблиотеку ( paramikofork):try: \n from ssh.config import SSHConfig \n except ImportError: \n from paramiko.config import SSHConfig
jfs
Библиотека SSH была снова объединена с Paramiko, напримерfrom paramiko.config import SSHConfig
n8henrie