相关问题本质上是在问同样的问题,但答案对我不起作用:
Make python enter password when running a csh script
How to interact with ssh using subprocess module
How to execute a process remotely using python
我想ssh到远程计算机并运行一个命令。例如:
ssh <user>@<ipv6-link-local-addr>%eth0 sudo service fooService status
问题是我试图通过只有标准库(没有pexpect
)的python脚本来实现这一点。我一直试图使用subprocess
模块使其工作,但是在请求密码时调用communicate
总是阻塞,即使我提供了密码作为communicate
的参数。例如:
proc = subprocess.Popen(
[
"ssh",
"{testUser1}@{testHost1}%eth0".format(**locals()),
"sudo service cassandra status"],
shell=False,
stdin=subprocess.PIPE)
a, b = proc.communicate(input=testPasswd1)
print "a:", a, "b:", b
print "return code: ", proc.returncode
我也尝试了上述的一些变体(例如,删除“input =”,添加/删除subprocess.PIPE
stdout
和sterr
的{{1}}分配。但是,结果始终是相同的提示:
ubuntu@<ipv6-link-local-addr>%eth0's password:
我错过了什么吗?或者有另一种方法可以使用python标准库实现这一目标吗?
答案 0 :(得分:5)
这个答案只是Torxed对this answer的改编,我建议你去投票。它只是添加了捕获您在远程服务器上执行的命令输出的功能。
import pty
from os import waitpid, execv, read, write
class ssh():
def __init__(self, host, execute='echo "done" > /root/testing.txt',
askpass=False, user='root', password=b'SuperSecurePassword'):
self.exec_ = execute
self.host = host
self.user = user
self.password = password
self.askpass = askpass
self.run()
def run(self):
command = [
'/usr/bin/ssh',
self.user+'@'+self.host,
'-o', 'NumberOfPasswordPrompts=1',
self.exec_,
]
# PID = 0 for child, and the PID of the child for the parent
pid, child_fd = pty.fork()
if not pid: # Child process
# Replace child process with our SSH process
execv(command[0], command)
## if we havn't setup pub-key authentication
## we can loop for a password promt and "insert" the password.
while self.askpass:
try:
output = read(child_fd, 1024).strip()
except:
break
lower = output.lower()
# Write the password
if b'password:' in lower:
write(child_fd, self.password + b'\n')
break
elif b'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
write(child_fd, b'yes\n')
else:
print('Error:',output)
# See if there's more output to read after the password has been sent,
# And capture it in a list.
output = []
while True:
try:
output.append(read(child_fd, 1024).strip())
except:
break
waitpid(pid, 0)
return ''.join(output)
if __name__ == "__main__":
s = ssh("some ip", execute="ls -R /etc", askpass=True)
print s.run()
输出:
/etc:
adduser.conf
adjtime
aliases
alternatives
apm
apt
bash.bashrc
bash_completion.d
<and so on>