使用 Fabric 时连接到 ~/. ssh/config 中列出的主机

我的 Fabric无法识别我在 ~/.ssh/config中的宿主。

我的 fabfile.py如下:

from fabric.api import run, env


env.hosts = ['lulu']


def whoami():
run('whoami')

运行 $ fab whoami的结果是:

跑,哇哦

致命错误: 名称查找失败 露露

lulu的名字在我的 ~/.ssh/config里,像这样:

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

我解决这个问题的第一个想法是向 /etc/hosts添加类似于 lulu.lulu的东西(我在 Mac 上) ,但是之后我还必须将身份文件传递给 Fabric ——我宁愿将身份验证(即 ~/.ssh/config)与部署(即 fabfile.py)分开。

另外,顺便说一句,如果你试图连接到主机文件中的主机,fabric.contrib.projects.rsync_project似乎不承认 hosts.env中的“端口”(即,如果你使用 hosts.env = [lulu:2100],一个对 rsync_project的调用似乎试图连接到 lulu:21)。

为什么 Fabric 不认识这个 lulu的名字?

28550 次浏览

update: This Answer is now outdated.


Fabric doesn't have support currently for the .ssh/config file. You can set these up in a function to then call on the cli, eg: fab production task; where production sets the username, hostname, port, and ssh identity.

As for rsync project, that should now have port setting ability, if not, you can always run local("rsync ...") as that is essentially what that contributed function does.

Note that this also happens when the name is not in /etc/hosts. I had the same problem and had to add the host name to both that file and ~/.ssh/config.

One can use following code to read the config (original code taken from: 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()

Since version 1.4.0, Fabric uses your ssh config (partly). However, you need to explicitly enable it, with

env.use_ssh_config = True

somewhere near the top of your fabfile. Once you do this, Fabric should read your ssh config (from ~/.ssh/config by default, or from env.ssh_config_path).

One warning: if you use a version older than 1.5.4, an abort will occur if env.use_ssh_config is set but there is no config file present. In that case, you can use a workaround like:

if env.ssh_config_path and os.path.isfile(os.path.expanduser(env.ssh_config_path)):
env.use_ssh_config = True