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

#coding=utf8'''
用python实现了一个简单的shell,了解进程创建
类unix 环境下 fork和exec 两个系统调用完成进程的创建
'''import sys, osdef 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:# childos.execvp(program_file, argv)sys.stderr.write("cannot exec: "+ cmdline)sys.exit(127)# parentpid, status = os.waitpid(pid, 0)ret = status >> 8  # 返回值是一个16位的二进制数字,高8位为退出状态码,低8位为程序结束系统信号的编号signal_num = status & 0x0Fsys.stdout.write("ret: %s, signal: %s\n" % (ret, signal_num))return retdef 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 selectnow_channel = Nonedef interactive_shell(chan):posix_shell(chan)def ioctl_GWINSZ(fd):try:cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'aaaa'))except:returnreturn crdef 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_channelnow_channel = chanresize_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.ICANONtry: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系统调用唤醒引发的系统中断,忽略中断重新调用解决。continueif chan in r:try:x = chan.recv(1024)if len(x) == 0:print 'rn*** EOFrn',breaksys.stdout.write(x)sys.stdout.flush()except socket.timeout:passif stdin in r:x = stdin.read(1)if len(x) == 0:breakchan.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相关推荐

  1. python ssh shell交互_python获取交互式ssh shell的方法

    更新,最近在学unix环境编程,了解一下进程的创建过程,用最原始的方式实现了一个ssh命令的执行. #coding=utf8 ''' 用python实现了一个简单的shell,了解进程创建 类unix ...

  2. 使用shell/python获取hostname/fqdn释疑(转)

    一直以来被Linux的hostname和fqdn(Fully Qualified Domain Name)困惑了好久,今天专门抽时间把它们的使用细节弄清了. 一.设置hostname/fqdn 在Li ...

  3. Python中操控ssh和sftp

    Python中操控ssh和sftp 1 Reply 在Python(其实任何语言都是)中操控ssh执行远程命令是一个很麻烦的事情-- 首先要突破ssh密码的非交互模式,我之前一直用sshpass拼接各 ...

  4. 在Linux上利用python获取本机ip

    下面介绍在Linux上利用python获取本机ip的方法. 经过网上调查, 发现大致有两种方法, 一种是调用shell脚本,另一种是利用python中的socket等模块来得到,下面是这两种方法的源码 ...

  5. 美观实用!Star 过万,用 Python 做交互式图形的这款工具火了!

    点击上方"Datawhale",选择"星标"公众号 第一时间获取价值内容 转自量子位,作者乾明 GitHub 上,一份用 Python 做交互式图形的资源火了. ...

  6. 超全!Python获取某一日期是“星期几”的6种方法!

    在Python进行数据分析时,按照日期进行分组汇总也是被需要的,比如会找到销量的周期性规律. 那么在用Python进行数据统计之前,就需要额外增加一步:从指定的日期当中获取星期几.比如2022年2月2 ...

  7. 使用 Python 获取 Linux 系统信息的代码

    From: http://www.jb51.net/article/52107.htm 在本文中,我们将会探索使用Python编程语言工具来检索Linux系统各种信息,需要的朋友可以参考下 哪个Pyt ...

  8. 使用Python获取Linux系统的各种信息

    From: http://www.jb51.net/article/52058.htm 这篇文章主要介绍了使用Python获取Linux系统的各种信息,例如系统类型.CPU信息.内存信息.块设备等,需 ...

  9. python相对路径下的shell_shell,python获取当前路径(脚本的当前路径) (aso项目记录)...

    一.shell获取脚本当前路径 cur_dir=$(cd "$(dirname "$0")"; pwd) #获取当前脚本的绝对路径,参数$0是当前脚本对象 等同 ...

  10. python自动保存ping结果_利用python获取Ping结果示例代码

    前言 本文主要跟大家分享了关于利用python获取Ping结果的相关内容,分享出来供大家参考学习,下面话不多说,来一起看看详细的介绍吧. 示例代码: # -*- coding: utf-8 -*- i ...

最新文章

  1. php读取本地xlsx格式文件的数据并按json格式返回
  2. 二叉查找树(二叉排序树)的详细实现
  3. 有趣的开源 AI 换脸工具:faceswap
  4. Struts2.3+Spring4.0
  5. SQL四种语言:DDL,DML,DCL,TCL
  6. php用存储过程插入数据,如何使用php-webservice使用android中的存储过程将数据插入sql数据库[duplicate]...
  7. 销售组织与工厂对照表
  8. 计算机心得300,计算机实训总结计算机实训心得300
  9. npm knowledge basics
  10. 分析 Go time.After 引起内存暴增 OOM 问题
  11. Python测试开发django3.视图和URL配置
  12. Kotlin-Note
  13. RS485使用串口输出最后一个字节固定为FF
  14. [美国]《霍比特人2:史矛革之战》[蓝光1080P.720P.中英双字][2013年奇幻动作]
  15. 快手接口分析(二)——关注
  16. C语言试题165之求三色旗问题
  17. echarts饼图 外圈转动动画 pie
  18. 分析师:百度到2030年可能成为中国市值最高的公司
  19. jxls2-java生成/导出excel工具!基于jxls2写的jxls增强版jxlss的完整教程
  20. 和菜鸟一起学证券投资之消费物价指数CPI

热门文章

  1. python字典与集合
  2. java对excel进行加密_用poi-3.6-20091214.jar 实现java给excel资料加密
  3. html mp4断点播放,html5解决大文件断点续传
  4. 国信安web安全——文件上传漏洞
  5. 专为程序员编写的英语学习指南
  6. Strategy模式简述
  7. 高级计量经济学及stata应用 学习笔记③ 长面板
  8. 免上传音乐外链(QQ音乐)
  9. 微信小程序实战十三:狗狗小程序云搭建
  10. 要求:弹出框接收字符串输入 输入aaabbbcccddd 输出3a3b3c3d