Connecting to a host listed in ~/.ssh/config when using Fabric
I'm having trouble with Fabric
not recognizing hosts that I have in ~/.ssh/config
.
My fabfile.py
is as follows:
from fabric.api import run, env
env.hosts = ['lulu']
def whoami():
run('whoami')
Running $ fab whoami
gives:
[lulu] run: whoami
Fatal error: Name lookup failed for lulu
The name lulu
is in my ~/.ssh/config
, like this:
Host lulu
hostname 192.168.100.100
port 2100
IdentityFile ~/.ssh/lulu-key
My first thought to solving this is adding something like lulu.lulu
to 开发者_Python百科/etc/hosts
(I'm on a Mac), but then I have to also pass in the identity file to Fabric - and I'd rather keep my authentication (i.e. ~/.ssh/config
) separate from my deployment (i.e. fabfile.py
).
As well, incidentally, if you try to connect to a host in the hosts file, fabric.contrib.projects.rsync_project
doesn't seem to acknowledge 'ports' in the hosts.env
(i.e. if you use hosts.env = [lulu:2100]
a call to rsync_project
seems to try connecting to lulu:21
).
Is there a reason Fabric doesn't recognize this lulu
name?
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
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
.
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.
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()
精彩评论