我正在使用Fabric在远程服务器上运行命令。我在该服务器上连接的用户具有一些sudo权限,并且不需要密码即可使用这些权限。当SSH进入服务器时,我可以运行sudo blah
并执行命令而不提示输入密码。当我尝试通过Fabric的sudo
函数运行相同的命令时,系统会提示我输入密码。这是因为Fabric在使用sudo
时以下列方式构建命令:
sudo -S -p <sudo_prompt> /bin/bash -l -c "<command>"
显然,我的用户无权在没有密码的情况下执行/bin/bash
。
我使用run("sudo blah")
代替sudo("blah")
解决了这个问题,但我想知道是否有更好的解决方案。这个问题有解决方法吗?
答案 0 :(得分:32)
尝试将shell=False
传递给sudo。那样/ bin / bash就不会被添加到sudo命令中。 sudo('some_command', shell=False)
来自fabric/operations.py的第503行:
if (not env.use_shell) or (not shell):
real_command = "%s %s" % (sudo_prefix, _shell_escape(command))
else块看起来像这样:
# V-- here's where /bin/bash is added
real_command = '%s %s "%s"' % (sudo_prefix, env.shell,
_shell_escape(cwd + command))
答案 1 :(得分:13)
您可以使用:
fabric.api import env
# [...]
env.password = 'yourpassword'
答案 2 :(得分:13)
这是您问题的最直接答案: 你实际上没有问题;你误解了Fabric run()和sudo()是如何工作的。
您的“解决方法”不是解决方法,它是对问题的100%有效答案。
这是一套简单的规则: 1)当你不期望提示时使用“run()”。 2)当你期望提示时使用“sudo()”。 (对于需要提示的所有或大多数命令,这应该是正确的,即使有问题的可执行文件不是Bash或Sudo)。
同样的答案适用于试图在“sudo”下运行命令的人。即使sudoers在某些系统上为当前用户配置了无密码配置,如果你使用sudo()而不是run(),那么你将强制提示(除非Fabric代码已经包含ENV密码或密钥)。
BTW的作者在#IRC中回答了我的问题 - 与你的问题非常相似。好人,开源的无名英雄之一坚持他的Fabric和Paramiko工作。
...在我的测试环境中,总有一个用户名具有对sudo的完全无密码访问权限。输入sudo echo hello
不会提示我。此外,该sudo用户配置了“!requiretty”,因此所有命令都可以通过SSH运行(如主机之间的SSH跳转)。这意味着我可以简单地使用“run()”来执行“sudo something”,但它只是另一个在没有提示的情况下运行的命令。就安全性而言,锁定生产主机而不是测试主机是某人的工作。 (如果您被迫通过并且无法自动化进行测试,那么这是一个很大的问题。)
答案 3 :(得分:6)
在/ etc / sudoers文件中添加
user ALL=NOPASSWD: some_command
其中user是你的sudo用户,some_command你要用fabric运行的命令,然后在fabric脚本上运行sudo it with shell = False:
sudo('some_command', shell=False)
这对我有用
答案 4 :(得分:2)
在/etc/sudoers
文件中,您可以添加
user ALL=NOPASSWD: /bin/bash
...其中user
是您的Fabric用户名。
显然,只有拥有root访问权限才能执行此操作,因为/etc/sudoers
只能由root写入。
同样显然,这并不是非常安全,因为能够执行/bin/bash
会让您对任何内容开放,所以如果您没有root访问权限并且必须让系统管理员为您执行此操作,他们可能不会。
答案 5 :(得分:1)
Linux noob在这里,但我在尝试将石墨织物安装到EC2 AMI时发现了这个问题。 Fabric继续提示输入root密码。
实际的诀窍是将ssh私钥文件传递给fabric。
fab -i key.pem graphite_install -H root@servername
答案 6 :(得分:1)
您还可以为多台计算机使用密码:
from fabric import env
env.hosts = ['user1@host1:port1', 'user2@host2.port2']
env.passwords = {'user1@host1:port1': 'password1', 'user2@host2.port2': 'password2'}
答案 7 :(得分:0)
我最近遇到了同样的问题,发现Crossfit_and_Beer的answer令人困惑。
实现此目标的支持方式是使用env.sudo_prefix
,this github commit(来自this PR)
我的使用示例:
env.sudo_prefix = 'sudo '