我想使用paramiko
ssh 进入一组远程节点并以root
特权运行一些命令行
我的主目录中有 ssh 密钥,因此当我通过 ssh 进入这些远程节点时,不需要输入密码
但运行以下脚本时:
def connect(hostname):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname, username='niky', pkey=paramiko.RSAKey.from_private_key(open('id_rsa'), 'passwd'), timeout = 240.0) return ssh
def run(hostname):
ssh = connect(hostname)
(stdin, stdout, stderr) = ssh.exec_command("sudo ls")
res = stderr.readlines()
print hostname+': '+''.join(str(elem) for elem in res)+'\n'
run(remote.nity.com)
我收到以下错误:
remote.nity.com: sudo: no tty present and no askpass program specified
如果在一切正常sudo
之前我不添加,可能的原因是什么?谢谢!ls
答案1
在库存sudoers
配置中,通常存在以下行:
Defaults requiretty
这既安全,也是您在大多数用例中所需要的。
对于您来说,您需要为特定用户覆盖此默认值,因此您可以在下面写入:
Defaults:niky !requiretty
另外,您需要定义一条允许无需密码niky
即可拨打的线路:sudo
niky remote.nity.com = (root)NOPASSWD: /bin/ls
此行的意思是允许用户niky
执行/bin/ls
而不root
需要remote.nity.com
密码。
更多参考资料请参见这里。
答案2
您会发现以下两件事很有用:
exec_command
接受可选参数get_pty
。您可以像这样使用它:(stdin, stdout, stderr) = ssh.exec_command("sudo ls", get_pty = True)
将密码输入到 中
stdin
,然后换行并刷新以确保密码被传递。这确保它在询问时收到密码(您可以做一些更复杂的操作来检查它是否真的询问过......简单地输入密码对我来说总是没有问题。)stdin.write('passwd' + '\n') stdin.flush()
综合起来,这些应该可以解决您的sudo
问题paramiko
。
答案3
仅供参考 - 可能有助于您的搜索 - 请注意,如果您将一个 SSH 命令封装在另一个命令中,您会在纯 SSH 中收到相同的错误,例如:
本地主机$ ssh[电子邮件保护]-C 'sudo su - 另一个用户 ssh[电子邮件保护]/运行/此/可执行文件'
(为什么不直接通过 SSH 连接到目标框?好吧,也许 SSH 密钥只设置在 host1 和 host2 之间,或者网络被路由为禁止不通过 host1 的 host2 访问。也许您无权接触 host2 上的 sudoers 或任何其他文件...在生产环境中很常见)。
无论如何,您都可以使用上述方法运行非 sudo 命令,但在前缀中添加 sudo 会导致“没有 tty present”。
如何使用裸 ssh 命令修复此问题?输入 -t,例如:localhost$ ssh[电子邮件保护]-C'sudo su-另一个用户 ssh-t[电子邮件保护]/运行/此/可执行文件'
现在远程 sudo 在 SSH 中运行良好,没有关于 tty 的投诉。-t 分配了它。
所以问题是,如何在 Paramiko 对象中模拟“-t”选项?这就是你的答案。
本博客尝试进行解释,但也许可以花更多时间在“sudo”示例上: http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/
(抱歉,我的观点只是指向正确的方向而不是完美的答案……实际上我自己仍在寻找这些信息)。