首页 > 编程 > Python > 正文

python获取交互式ssh shell的方法

2020-02-16 01:07:34
字体:
来源:转载
供稿:网友

更新,最近在学unix环境编程,了解一下进程的创建过程,用最原始的方式实现了一个ssh命令的执行。

#coding=utf8 '''用python实现了一个简单的shell,了解进程创建类unix 环境下 fork和exec 两个系统调用完成进程的创建''' import sys, os  def myspawn(cmdline): argv = cmdline.split() if len(argv) == 0:  return  program_file = argv[0] pid = os.fork() if pid < 0:  sys.stderr.write("fork error") elif pid == 0:  # child  os.execvp(program_file, argv)  sys.stderr.write("cannot exec: "+ cmdline)  sys.exit(127) # parent pid, status = os.waitpid(pid, 0) ret = status >> 8 # 返回值是一个16位的二进制数字,高8位为退出状态码,低8位为程序结束系统信号的编号 signal_num = status & 0x0F sys.stdout.write("ret: %s, signal: %s/n" % (ret, signal_num)) return ret  def ssh(host, user, port=22, password=None): if password:  sys.stdout.write("password is: '%s' , plz paste it into ssh/n" % (password)) cmdline = "ssh %s@%s -p %s " % (user, host, port) ret = myspawn(cmdline)  if __name__ == "__main__": host = '' user = '' password = '' ssh(host, user, password=password)

最近在做一个项目,需要在客户端集成一个交互式ssh功能,大概就是客户端跟服务器申请个可用的机器,服务端返回个ip,端口,密码, 然后客户端就可以直接登录到机器上操做了。该程序基于paramiko模块。

经查找,从paramiko的源码包demos目录下,可以看到交互式shell的实现,就是那个demo.py。但是用起来有些bug,于是我给修改了一下interactive.py(我把windows的代码删掉了,剩下的只能在linux下用)。代码如下:

#coding=utf-8import socketimport sysimport osimport termiosimport ttyimport fcntlimport signalimport structimport select now_channel = None def interactive_shell(chan): posix_shell(chan)  def ioctl_GWINSZ(fd): try:  cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'aaaa')) except:  return return cr  def getTerminalSize(): cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) return int(cr[1]), int(cr[0])  def resize_pty(signum=0, frame=0): width, height = getTerminalSize() if now_channel is not None:  now_channel.resize_pty(width=width, height=height)   def posix_shell(chan): global now_channel now_channel = chan resize_pty() signal.signal(signal.SIGWINCH, resize_pty) # 终端大小改变时,修改pty终端大小 stdin = os.fdopen(sys.stdin.fileno(), 'r', 0) # stdin buff置为空,否则粘贴多字节或者按方向键的时候显示不正确 fd = stdin.fileno() oldtty = termios.tcgetattr(fd) newtty = termios.tcgetattr(fd) newtty[3] = newtty[3] | termios.ICANON try:  termios.tcsetattr(fd, termios.TCSANOW, newtty)  tty.setraw(fd)  tty.setcbreak(fd)  chan.settimeout(0.0)  while True:   try:    r, w, e = select.select([chan, stdin], [], [])   except:    # 解决SIGWINCH信号将休眠的select系统调用唤醒引发的系统中断,忽略中断重新调用解决。    continue   if chan in r:    try:     x = chan.recv(1024)     if len(x) == 0:      print 'rn*** EOFrn',      break     sys.stdout.write(x)     sys.stdout.flush()    except socket.timeout:     pass   if stdin in r:    x = stdin.read(1)    if len(x) == 0:     break    chan.send(x) finally:  termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表