更新,最近在学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-8 import socket import sys import os import termios import tty import fcntl import signal import struct import 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)
使用示例:
#coding=utf8 import paramiko import interactive #记录日志 paramiko.util.log_to_file('/tmp/aaa') #建立ssh连接 ssh=paramiko.SSHClient() ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('192.168.1.11',port=22,username='hahaha',password='********',compress=True) #建立交互式shell连接 channel=ssh.invoke_shell() #建立交互式管道 interactive.interactive_shell(channel) #关闭连接 channel.close() ssh.close()
interactive.py代码中主要修复了几个问题:
1、当读取键盘输入时,方向键会有问题,因为按一次方向键会产生3个字节数据,我的理解是按键一次会被select捕捉一次标准输入有变化,但是我每次只处理1个字节的数据,其他的数据会存放在输入缓冲区中,等待下次按键的时候一起发过去。这就导致了本来3个字节才能完整定义一个方向键的行为,但是我只发过去一个字节,所以终端并不知道我要干什么。所以没有变化,当下次触发按键,才会把上一次的信息完整发过去,看起来就是按一下方向键有延迟。多字节的粘贴也是一个原理。解决办法是将输入缓冲区置为0,这样就没有缓冲,有多少发过去多少,这样就不会有那种显示的延迟问题了。
2、终端大小适应。paramiko.channel会创建一个pty(伪终端),有个默认的大小(width=80, height=24),所以登录过去会发现能显示的区域很小,并且是固定的。编辑vim的时候尤其痛苦。channel中有resize_pty方法,但是需要获取到当前终端的大小。经查找,当终端窗口发生变化时,系统会给前台进程组发送SIGWINCH信号,也就是当进程收到该信号时,获取一下当前size,然后再同步到pty中,那pty中的进程等于也感受到了窗口变化,也会收到SIGWINCH信号。
3、读写‘慢'设备(包括pipe,终端设备,网络连接等)。读时,数据不存在,需要等待;写时,缓冲区满或其他原因,需要等待。ssh通道属于这一类的。本来进程因为网络没有通信,select调用为阻塞中的状态,但是当终端窗口大小变化,接收到SIGWINCH信号被唤醒。此时select会出现异常,触发系统中断(4, 'Interrupted system call'),但是这种情况只会出现一次,当重新调用select方法又会恢复正常。所以捕获到select异常后重新进行select可以解决该问题。
以上这篇python获取交互式ssh shell的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]