I have upgraded fabric from fabric3==1.14.post1 to fabric=2.5.0. Code works fine with fabric3==1.14.post1.
And now i have a problem while executing tasks inner another tasks.
The problem is that, when i run task, task must update and install soft in remote server which connects without password(with public key, don't ask password!).
Old version(1.14.post1):
from fabric.api import task, sudo, env, run
#task
def install_docker():
sudo('apt-get update && apt-get install -qy docker.io')
#task
def task_queue():
execute(install_docker)
execute(install_some_soft)
How I run it: fab task_queue
New version(2.5.0)
#task
def install_docker(ctx):
ctx.sudo('apt-get update && apt-get install -qy docker.io')
#task(pre=[install_docker])
def task_queue(ctx):
pass
How I run it: fab task-queue
And i'm hiving error like this:
invoke.exceptions.AuthFailure: The password submitted to prompt '[sudo] password: ' was rejected.
Use --prompt-for-sudo-password when you run fab.
Related
My request is simple:
ssh to a remote server with user0
switch user to user1 using: 'sudo su user1'
list all items in current folder
My expected code:
def startRedis():
run('sudo su - user1')
print(run('ls'))
However, it ends with out: user1#server:~$
And waiting for my interactive command forever, never executing the second line. It seems sudo su opened a new shell.
Can anyone help solving this simple task?
You can set sudo_user property in env. this way fabric will switch user to the desired user.
Official doc: http://docs.fabfile.org/
Password for switching user can be specified in the env. itself to avoid getting a prompt when the method is invoked.
fabfile.py
from fabric.api import env, sudo
env.sudo_user='user1'
env.password = '***'
def list_items():
sudo('ls')
Run below command & specify the hosts after -H
fab -H host1 list_items
I'm wondering what is the difference between the function sudo() and the function run('sudo -u user smth')
On the doc there is :
sudo is identical in every way to run, except that it will always wrap
the given command in a call to the sudo program to provide superuser
privileges.
But a few time, sudo('cmd') prompt me a password, but if I switch with run('sudo cmd') it works without prompting me anything. Is there anything that change between the two ? (I remember someone on SO saying that sudo and run(sudo cmd) are not for the same use, but I can't find it back)
I found these two difference.
1: Fabric maintains an in-memory password
2: sudo accepts additional user and group arguments
First, fabric would get password from cache when using sudo(), then you do not need to enter password. But if you use run('sudo cmd'), you need to enter password for each 'sudo cmd'.
Second, if you want to execute a command not under root but other user group like www, you just need to set env.sudo_user = 'www' or sudo('cmd', user='www'). The first would execute each sudo() under www, the second would execute this single cmd under www. But you need to edit to run("sudo -u 'www' cmd") when use run() command.
from fabric.api import sudo, run, env
env.hosts = ['host_ip',]
env.user = 'user_name'
env.sudo_user = 'sudo_user'
def test_1():
run('sudo pwd')
def test_2():
sudo('pwd')
$ fab -I --show=debug test_1 test_2
Initial value for env.password: # enter password
Commands to run: test_1, test_2
Parallel tasks now using pool size of 1
[ip_address] Executing task 'test_1'
[ip_address] run: /bin/bash -l -c "sudo pwd"
[ip_address] out: [sudo] password for billy: # needs to enter password here
[ip_address] out: /home/billy
[ip_address] out:
Parallel tasks now using pool size of 1
[ip_address] Executing task 'test_2'
[ip_address] sudo: sudo -S -p 'sudo password:' -u "root" /bin/bash -l -c "pwd"
[ip_address] out: sudo password: # only prompt, do not need enter password
[ip_address] out: /home/billy
[ip_address] out:
Done.
Disconnecting from ip_address... done.
Since Fabric 2, you can invoke sudo via run(), which will prompt for the password unless you use the auto-responder, details here. Note that the sudo command usually caches the password remotely, so next invocations of sudo during the same connection will not prompt for password.
However, the Fabric sudo() helper makes using sudo much easier, details here. You need to ensure that the sudo.password configuration value is filled in (via config object, config file, environment variable, or --prompt-for-sudo-password). Here's how I do it with the keyring module:
from fabric import task
import keyring
#task
def restart_apache(connection):
# set the password with keyring.set_password('some-host', 'some-user', 'passwd')
connection.config.sudo.password = keyring.get_password(connection.host, 'some-user')
connection.sudo('service apache2 restart')
I'm pretty new to python and fabric and I am trying to do a simple code where I can get the output on two hosts that uses sudo, although I keep getting an error.... Can anyone help me out with what I might be missing ?
My code:
from fabric.api import *
from getpass import getpass
from fabric.decorators import runs_once
env.hosts = ['host1','host2']
env.port = '22'
env.user = 'username'
env.password="password"
def sudo_dsmc(cmd):
sudo("-l")
When I run: fab sudo_dsmc:"-1" :
MacBookPRO:PYTHON username$ fab sudo_dsmc:"-l"
[host1] Executing task 'sudo_dsmc'
[host1] sudo: -l
[host1] out: sudo password:
[host1] out: Sorry, user username is not allowed to execute '/bin/bash -l -c - l' as root on host1.
[host1] out:
Fatal error: sudo() received nonzero return code 1 while executing!
Requested: -l
Executed: sudo -S -p 'sudo password:' /bin/bash -l -c "-l"
Aborting.
Disconnecting from host1... done.
Although I can run the apt-get update with my below function fine without any errors:
def sudo_command(cmd):
sudo("apt-get update")
# run like: fab sudo_command:"apt-get-update"
It looks like your sudoers file is preventing you from running that command as sudo. Check your /etc/sudoers file and read the sudo documentation.
Also "-l" isn't a valid command. sudo takes -l as an optional flag (which lists commands allowed by the user). But Fabric's sudo appears to be taking unknown strings and routing them through /bin/bash instead of using them directly as sudo command parameters.
I want to deploy my code in localhost and my live version for this automation i used fabric. My basic fabric file look like:
def localhost():
"Use the local virtual server"
env.hosts = ['127.0.0.1']
env.user = 'user'
env.path = '/var/www/html/{}'.format(env['project_name'])
env.virtualhost_path = env.path
def webserver():
"Use the actual webserver"
env.hosts = ['www.example.com']
env.user = 'username'
env.path = '/var/www/html/{}'.format(env['project_name'])
env.virtualhost_path = env.path
def setup():
require('hosts', provided_by=[localhost])
require('path')
sudo("apt-get update -y")
sudo("apt-get install git -y")
sudo("apt-get install postgresql libpq-dev python-dev python-pip -y")
sudo("apt-get install redis-server -y")
sudo("apt-get install nginx -y")
sudo('aptitude install -y python-setuptools')
sudo('apt-get install python-pip')
sudo('pip install virtualenv virtualenvwrapper')
For now i only want to deploy to my local machine. When I do this it gives me erro saying
The command 'setup' failed because the following required environment variable was not defined:
hosts
Try running the following command prior to this one, to fix the problem:
localhost
What does provided_by=([localhost]) do in here. I guess it should provide the information like hosts and user in localhost.
Why I am getting this error ??
Need help
I'm not sure why that doesn't work other than it's not mentioned in the docs as how host lists get constructed. Your options for setting the host value are:
Specify env.hosts = ['127.0.0.1'] globally in your fabfile
Pass the host to fab: fab -H 127.0.0.1 setup
Call the localhost task: fab localhost setup
Use the #hosts decorator on your setup function
See http://docs.fabfile.org/en/1.10/usage/execution.html#how-host-lists-are-constructed
fabric.operations.require(*keys, **kwargs):
Check for given keys in the shared environment dict and abort if not
found... The optional keyword argument provided_by may be a list of functions or function names or a single function or function name which the user should be able to execute in order to set the key or keys; it will be included in the error output if requirements are not met.
http://docs.fabfile.org/en/1.10/api/core/operations.html?highlight=require#fabric.operations.require
That why you get the error message saying to run localhost first, then setup:
fab localhost setup
I am having some problems with commands that have sudo using paramiko
f.ex sudo apt-get update
here is my code:
try:
import paramiko
except:
try:
import paramiko
except:
print "There was an error with the paramiko module"
cmd = "sudo apt-get update"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect("ip",username="lexel",password="password")
print "succesfully conected"
except:
print "There was an Error conecting"
stdin, stdout, stderr = ssh.exec_command(cmd)
stdin.write('password\n')
stdin.flush()
print stderr.readlines()
print stdout.readlines()
This is a quick code. I know that I need to add sys.exit(1) and all that but this is just to demostration
I used this for reference:
Jessenoller.com
Fabric has sudo command. It uses Paramico for ssh connections. Your code would be:
#fabfile.py
from fabric.api import run, sudo
def update():
"""Run `sudo apt-get update`.
lorem ipsum
"""
sudo("apt-get update")
def hostname():
"""Run `hostname`"""
run("hostname")
Usage:
$ fab update -H example.com
[example.com] Executing task 'update'
[example.com] sudo: apt-get update
...snip...
[example.com] out: Reading package lists... Done
[example.com] out:
Done.
Disconnecting from example.com... done.
$ fab --display update
Displaying detailed information for task 'update':
Run `sudo apt-get update`.
lorem ipsum
$ fab --list
Available commands:
hostname Run `hostname`
update Run `sudo apt-get update`.
From the docs:
In addition to use via the fab tool, Fabric’s components may be
imported into other Python code, providing a Pythonic interface to the
SSH protocol suite at a higher level than that provided by e.g.
Paramiko (which Fabric itself leverages.)
I was having the same problem, and I fix with this:
In your sudo file, just add this:
Defaults:your_username !requiretty
or remove Defaults requiretty.
Also make sure your user have permission to run the command with sudo.