简体   繁体   中英

Python Fabric : Executing functions on different hosts with different passwords, in the same script

I'm currently trying to automate a deployment process, involving 3 different machines :

  • userA@hostA, pwdA
  • userB@hostB, pwdB
  • userC@hostC, pwdC

Here's the scenario I would like to execute, using Python's Fabric library (to which I'm new) :

def deploy():
    execute(taskA, hosts=[hostA])
    execute(taskB, hosts=[hostB])
    execute(taskC, hosts=[hostC])

I've tried to set the variable env.passwords like this:

env.passwords = {'userA@hostA:22':pwdA, 'userB@hostB:22':pwdB, 'userC@hostC:22':pwdC}

But it makes the SSH connection hanging.

My current workaround is to modify the variables env.user and env.password before each call to execute (I could also do that at the beginning of taskA, taskB and taskC). I really do not find that very elegant, and totally outside of Fabric's spirit.

If someone has ran into such situation, found him/herself with a hanging SSH connection while trying to use the env.passwords dict, I'm all yours ! And of course, if anyone already managed to make a more elegant multi-host-password handling, I would be glad to hear about any hint.

It might be better to keep your ssh details in ~/.ssh/config and have Fabric use that. See

As said in my comment above, using the use_ssh_config variable works well. But in case you SSH with a password, Fabric currently doesn't handle per-host/per-user/per-password connection (which is normal, since using SSH passwords is considered as insecure)

That's why I dug into Fabric's source code, and added that new "feature". Here is my repository if you want to have a look. Basically, I used the env.roledefs variable, which lists roles as dictionary entries. And each role has a list of hosts, a user, and a password. Now, if you want to execute a task in one or more hosts (which have different usernames and passwords), there are two ways to do it:

  • Annotating the task with the decorator @complete_roles('role1', 'role2')
  • Using the function execute(task, complete_roles=['role1', 'role2'])

Just be sure to have 'role1' and 'role2' as keys in env.roledefs

If you want to have more info about my contribution, just check the two latest commits. I know, my code is not the cleanest...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM