使用os.forkpty()创建伪终端以SSH连接远程服务器并进行通信
我正在尝试写一个Python脚本,这个脚本可以通过SSH连接到远程服务器,并且能够从Python客户端执行一些简单的命令,比如ls(列出文件)和cd(切换目录)。但是,在成功连接到服务器后,我无法读取伪终端的输出。有没有人能帮我一下,让我可以在服务器上执行一些命令。
以下是示例代码:
#!/usr/bin/python2.6
import os,sys,time,thread
pid,fd = os.forkpty()
if pid == 0:
os.execv('/usr/bin/ssh',['/usr/bin/ssh','user@host',])
sys.exit(0)
else:
output = os.read(fd,1024)
print output
data = output
os.write(fd,'password\n')
time.sleep(1)
output = os.read(fd,1024)
print output
os.write(fd,'ls\n')
output = os.read(fd,1024)
print output
示例输出:
user@host's password:
Last login: Wed Aug 24 03:16:57 2011 from 1x.x.x.xxxx
-bash: ulimit: open files: cannot modify limit: Operation not permitted
host: /home/user>ls
2 个回答
2
正如之前提到的,最好使用公钥。因为我通常都是这样做的,所以我对你的程序进行了修改,使它在这里可以正常工作。
#!/usr/bin/python2.6
import os,sys,time,thread
pid,fd = os.forkpty()
if pid == 0:
os.execv('/usr/bin/ssh',['/usr/bin/ssh','localhost',])
sys.exit(0)
else:
output = os.read(fd,1024)
print output
os.write(fd,'ls\n')
time.sleep(1) # this is new!
output = os.read(fd,1024)
print output
通过添加 sleep(1)
,我给远程主机(或者在我的情况下,不是那么远的主机)留出时间来处理 ls
命令并生成输出。
如果你发送 ls
命令后立刻读取,你只会得到当前存在的内容。也许你应该在一个循环中读取一下。
或者你可以这样做:
import subprocess
sp = subprocess.Popen(("ssh", "localhost", "ls"), stdout=subprocess.PIPE)
print sp.stdout.read()
3
我建议你试试一个叫做pexpect的模块,它就是为了处理这种情况而设计的(通过伪终端与其他应用程序进行交互)。还有一个叫Fabric的工具,它更抽象一些,主要用于自动化远程服务器上的系统管理任务,通常是通过SSH来实现。
pexpect: http://pypi.python.org/pypi/pexpect/
Fabric: http://docs.fabfile.org/en/1.11/