fabric difference sudo() run('sudo cmd')
Asked Answered
L

2

8

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)

Louls answered 13/7, 2016 at 7:25 Comment(0)
H
5

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.
Hitch answered 11/1, 2017 at 12:27 Comment(0)
X
2

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')
Xenophanes answered 28/12, 2018 at 21:47 Comment(1)
How to prevent fabric asking for a password when using run?Arva

© 2022 - 2024 — McMap. All rights reserved.