结构差异 sudo() 运行('sudo cmd')

fabric difference sudo() run('sudo cmd')

我想知道函数 sudo() 和函数 run('sudo -u user smth')

有什么区别

文档上有:

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.

但有几次,sudo('cmd') 会提示我输入密码,但如果我用 run('sudo cmd') 切换,它会在不提示我任何东西的情况下工作。两者之间有什么变化吗? (我记得有人在 SO 上说 sudorun(sudo cmd) 不是同一个用途,但我找不到了)

我发现了这两个区别。

1: Fabric maintains an in-memory password

2: sudo accepts additional user and group arguments

首先,fabric在使用sudo()时会从缓存中获取密码,然后就不需要输入密码了。但是如果你使用运行('sudo cmd'),你需要为每个'sudo cmd'.

输入密码

其次,如果你想执行的命令不是在root下而是其他用户组如www,你只需要设置env.sudo_user = 'www'或sudo('cmd', user ='www')。第一个将在 www 下执行每个 sudo(),第二个将在 www 下执行单个 cmd。但是在使用 运行() 命令时需要编辑为 运行("sudo -u 'www' cmd")。

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.

从 Fabric 2 开始,您可以通过 run() 调用 sudo,这将提示您输入密码,除非您使用自动回复器 details here。请注意,sudo 命令通常会远程缓存密码,因此在同一连接期间下次调用 sudo 将不会提示输入密码。

但是,Fabric sudo() 帮助程序使使用 sudo 变得更加容易,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 模块:

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')