【简洁明了】xterm.js+paramiko+websocket实现Web终端,可ssh连接linux bash

本文介绍了如何使用xterm.js、paramiko和websocket技术在Web端实现SSH连接到Linux服务器的终端。通过paramiko进行Python的SSH交互,结合websocket进行前后端通信,利用xterm.js在前端展示交互式终端。同时,文章讨论了在实现过程中遇到的问题及解决方案,包括命令执行、提示符判断和性能优化。
摘要由CSDN通过智能技术生成

项目要求,需要在web使用ssh或者控制台,就找有没有好的方法可以实现,找到了xterm.js+paramiko+websocket等实现交互,xtarm.js可以在前端展示一个终端,可以自定义,通过websocket和后端进行通信,后端可以自己写一个脚本程序,配置一个websocket的server端进行通信。
paramiko

python执行终端命令

在这里我本来想的是直接在python里调用终端命令执行,但是单独使用的时候可以,集成起来就不好用了,为什么不好用后面说,先说几种常用的终端命令的执行。

os.system

import os
os.system('ls')

会启动一个子进程调用command执行命令,在终端直接执行会显示结果,在程序中使用只会有返回值,结果不会返回。

os.popen

os.popen(command,mode)

import os
os.popen('cat /proc/cpuinfo')

直接与command进程通信的一个管道,返回一个文件对象,mode可以指定模式,如果是’r’,可以使用read()或者readlines()方法读取返回的执行结果。

commands

import commands
status=commands.getstatus('cat /proc/cpuinfo')
output=commands.getoutput('ls -l')
(status,output)=commands.getstatusoutput('ls -l')

会返回一个元组,包含执行结果和返回的状态。output中包含了控制台的输出信息和错误信息等。

subprocess

是python2.4出现的一个模块,可以代替上面的模块方法,还集中了多个关于进程的操作。call()完全替代了system()popen()Popen类进行实现和完善。

websocket

这个没什么好介绍的(就是我不想写,直接百度都是,而且主要是看实现的过程,概念这些东西估计也没多少人想看)。
主要就是,它是socket的更高级版本吧,然后呢,可以双方都使用websocket进行通信,会比较方便;也可以使用socket进行,如python中使用socket实现服务端,客户端使用websocket进行连接。
但是会非常麻烦,需要自己处理握手通信以及数据的编码解码等处理操作,虽然网上可以找到很多,但是我看了好些综合了好几个博客的代码,都没有实现,接收到的数据都是乱码,而且我传输的都是英文,没有中文,也不涉及编码混乱的问题,因此呢,手动实现就可以放弃了。
然后我找到由第三方库实现websocket的功能。

websockets

这是github
但是好像需要python3版本才行,我是2,就放弃了。

simple-websocket-server

这是github
这个我试了一下很好用,主要是很方便,把websocket的操作都封装好了,直接使用就行了,
官方示例如下,看代码也不用多解释,建立一个连接,然后新建一个类,有三个方法处理三个事件就好了。

from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket

class SimpleEcho(WebSocket):

    def handleMessage(self):
        # echo message back to client
        self.sendMessage(self.data)

    def handleConnected(self):
        print(self.address, 'connected')

    def handleClose(self):
        print(self.address, 'closed')

server = SimpleWebSocketServer('', 8000, SimpleEcho)
server.serveforever()

问题来了,就是在这里,单独用脚本执行commands.getstatusoutput没有问题,但是放在这个框架里就有问题来了,所以在这里没法用。
然后呢,这个框架有点问题,如果你的程序在运行中突然断开连接了,或者刚连上就断开了,说明代码有问题,这个库代码出错是不会报错的,只会断开连接。善用print调试,定位出错位置。

paramiko

ssh是一个协议,OpenSSH是其中一个开源实现,paramiko是Python的一个库,实现了SSHv2协议(底层使用cryptography)。

有了Paramiko以后,我们就可以在Python代码中直接使用SSH协议对远程服务器执行操作,而不是通过ssh命令对远程服务器进行操作。
安装的话,直接pip就行了

pip install paramiko

这里只介绍SSHClient
基本使用如下

def sshConnection():
	ip    = '192.168.1.104'
	port  = 22
	user  = 'root'
	passwd= 'root'

	cmd = 'cd /home/kang/Desktop'
	# 设置记录日志
	log_file = 'kali_ssh.log'
	util.log_to_file(log_file)

	# 生成ssh客户端实例
	s = SSHClient()
	s.set_missing_host_key_policy(AutoAddPolicy())
	print ("[+] Start ssh into: "+ip)
	s.connect(ip, port, user, passwd)
	print ("[+] SSH established !")
	s.exec_command('ls -l')
	recv=s.recv(1024)
	print(recv)
	chan.close()
	s.close()

非交互式:ssh_client.exec_command

但是有一个小问题,这里如果使用exec_command,他是非交互式的,差不多就是每次只能执行一条,如果需要使用环境变量啥的,就不行了,得bash -ls 'ls -l’才行。如果需要执行多条语句,使用;分隔开。
而且如果出现比如进入python终端这种情况,exec_command就无法执行了,会卡住,可能是无法判断出后台终端的响应。

交互式:channel.invoke_shell

比较推荐的是交互式的方式,相当于创建一个shell终端,在其中运行命令,但是这个的问题是,如何判断命令是否执行完成,如果等的时间太短可能获取不到结果,如果等的时间太长用户体验不好。
这里通过返回的SP1输入提示符进行判断,在返回结果的最后都会返回一个输入的提示符,而每个界面或者系统的提示符不同,可能会有# 结尾的,也可能是$ 结尾的。因此可以把这些添加到一个list中,进行判断。
下面是一个示例

import paramiko
import time
 
hostname = '192.16.21.12'
port = 22
username = 'hadoop'
password = 'hadoop'
timeout = 10
 
 
def runCommand
要在 Vue 中使用 xterm.jsWebSocket 实现终端,你需要将用户输入的命令发送给后端,然后将后端返回的结果输出到 xterm.js 终端中。以下是一个简单的示例: ```html <template> <div id="terminal"></div> </template> <script> import { Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; export default { data() { return { socket: null, // WebSocket 实例 term: null, // Terminal 实例 }; }, mounted() { // 创建 WebSocket 实例 this.socket = new WebSocket('ws://localhost:8080'); // 创建 Terminal 实例 this.term = new Terminal(); const fitAddon = new FitAddon(); this.term.loadAddon(fitAddon); this.term.open(document.getElementById('terminal')); // 处理 WebSocket 消息 this.socket.onmessage = (event) => { this.term.write(event.data); }; // 处理输入事件 this.term.onData(data => { this.socket.send(data); }); // 调整终端大小 this.term.onResize(size => { const cols = size.cols; const rows = size.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }); // 发送 resize 消息 const cols = this.term.cols; const rows = this.term.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }, beforeDestroy() { // 关闭 WebSocket 连接 this.socket.close(); } } </script> ``` 以上代码中,我们首先在 `mounted` 钩子函数中创建了一个 WebSocket 实例和一个 Terminal 实例。然后我们为 WebSocket 实例添加了一个 `onmessage` 事件监听器,该监听器会在接收到服务器返回的消息时触发,我们在该事件处理函数中将消息输出到终端中。 接着,我们为 Terminal 实例添加了一个 `onData` 事件监听器,该监听器会在用户输入时触发,我们在该事件处理函数中向服务器发送用户输入的命令。同时,我们还为 Terminal 实例添加了一个 `onResize` 事件监听器,该监听器会在终端大小调整时触发,我们在该事件处理函数中向服务器发送终端大小变化的消息。 最后,我们在 `beforeDestroy` 钩子函数中关闭了 WebSocket 连接。 需要注意的是,以上代码中的 WebSocket 连接是通过 `ws://localhost:8080` 连接本地服务器的,你需要根据实际情况修改 WebSocket 连接地址。另外,代码中的消息格式和处理逻辑也需要根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值