更新,最近在学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)
新闻热点
疑难解答