惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News | PayPal Newsroom
P
Proofpoint News Feed
Cyberwarzone
Cyberwarzone
C
Cisco Blogs
SecWiki News
SecWiki News
Know Your Adversary
Know Your Adversary
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Vercel News
Vercel News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
NISL@THU
NISL@THU
WordPress大学
WordPress大学
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Threat Research - Cisco Blogs
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
Security Archives - TechRepublic
Security Archives - TechRepublic
有赞技术团队
有赞技术团队
L
LINUX DO - 热门话题
Hacker News: Ask HN
Hacker News: Ask HN
V
V2EX
G
GRAHAM CLULEY
TaoSecurity Blog
TaoSecurity Blog
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
F
Fortinet All Blogs
博客园 - 叶小钗
博客园 - 三生石上(FineUI控件)
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
Latest news
Latest news
The Hacker News
The Hacker News
aimingoo的专栏
aimingoo的专栏
T
Troy Hunt's Blog
S
Schneier on Security
I
Intezer
Google DeepMind News
Google DeepMind News
A
Arctic Wolf
Apple Machine Learning Research
Apple Machine Learning Research
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threatpost
爱范儿
爱范儿
The Register - Security
The Register - Security
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
宝玉的分享
宝玉的分享
Recent Commits to openclaw:main
Recent Commits to openclaw:main
美团技术团队
B
Blog RSS Feed

HaoKunT的博客

如何用 ollama 快速下载 deepseek 模型 - HaoKunT的博客 python使用gdal - HaoKunT的博客 Word中写LaTeX公式 - HaoKunT的博客 g++中的rpath和runpath - HaoKunT的博客 Ext4文件系统 - HaoKunT的博客 文件系统介绍 - HaoKunT的博客 理解shell - HaoKunT的博客 Hyper V安装ENVI - HaoKunT的博客 华为软件实习生笔试 - HaoKunT的博客 用C++实现一个命令行进度条 - HaoKunT的博客 PCA与GWPCA - HaoKunT的博客 字节后台实习生笔试题目 - HaoKunT的博客 阿里云API网关与函数计算的基础理解 - HaoKunT的博客 函数计算搭建DNS服务器 - HaoKunT的博客 DNS解析过程 - HaoKunT的博客 Github图片加载不出来 - HaoKunT的博客 将Elementary OS装在U盘中 - HaoKunT的博客 MacOS+Windows 双系统的安装 - HaoKunT的博客 IPXE+netboot+ISCSI 网络启动 - HaoKunT的博客 Esxi+NAS+Openwrt - HaoKunT的博客 Esxi的安装和使用 - HaoKunT的博客 利用acme自动更新证书 - HaoKunT的博客 Golang使用海康威视SDK - HaoKunT的博客 Filetools工具 - HaoKunT的博客 学习正则表达式 - HaoKunT的博客 Vugu View - HaoKunT的博客 Django Restframework 嵌套序列化 - HaoKunT的博客 看不了netlify的部署日志 - HaoKunT的博客 Go Modules的使用 - HaoKunT的博客 使用hugo+netlify部署个人主页 - HaoKunT的博客 关于我 - HaoKunT的博客 在线工具大全 - HaoKunT的博客 SWIG编译海康威视SDK 使用golang - HaoKunT的博客 SWIG 以Python为例 - HaoKunT的博客 Seafile - HaoKunT的博客 Golang的小技巧 - HaoKunT的博客 归档 - HaoKunT的博客 搜索 - HaoKunT的博客
Web终端仿真器 - HaoKunT的博客
HaoKunT · 2020-03-06 · via HaoKunT的博客

本文为原创文章,转载注明出处,欢迎关注网站https://hkvision.cn

背景

​ 在我的上一篇文章中已经说过了,我想做一个web命令行。但是呢,我这两天碰到了一些问题,主要是基础不牢引起的一些概念性的问题,导致我在搜索资料的时候花费了很多时间。

​ 最开始我碰到的问题是我在执行git clone命令的时候,我发现如果我把执行结果重定向到一个文件上,或者是我用Golang的exec.Command命令执行的时候将结果用管道扔到我的程序里,执行的结果就只有一行Cloning xxx into xxx...,而正常的结果应该是像这样的

​ 这个问题我一开始以为是clone的进度是一个类似于进度条,导致这种进度条无法被重定向,一度找问题找错了方向。后来发现不是这个原因,我在这个地方找到了原因,原来是因为git这个命令,将stdout和stderr赋予了不同的涵义,stderr是一个人更感兴趣的输出,而stderr是机器更感兴趣的输出,因此有一个静默模式,就是说在git发现输出的终点不是一个终端(terminal)的时候,将默认不将人感兴趣的内容输出,也就是更加的安静(quiet),在git的文档中我们也可以发现这点,这里引文档的这段话

–progress

Progress status is reported on the standard error stream by default when it is attached to a terminal, unless --quiet is specified. This flag forces progress status even if the standard error stream is not directed to a terminal.

​ 好,找到这个问题了,我们的目标就是让程序的输出变成一个终端。首先要明确的是什么是终端,这里因为我的概念不熟悉的原因又将我引入了死路,我在github上搜索的关键词一直是webshell,这倒是让我搜出来了一些东西,但是重点是并不是我想要的,例如我找到了很多个在web上执行自定义命令的,啊反正很多。直到我找到了这篇文章,这篇文章一扫我心中的阴霾,简直就是豁然开朗。

​ 那么到底是什么问题呢?实际上我将shellterminal这两个东西弄混了,相信很多人也是像我这样的。具体的大家去看这篇文章,我这里简单的说一下。shell是和bash,sh,zsh对应的,terminal是和tty对应的,相信大家对这几个内容肯定有所耳闻,我平时接触到的肯定是bash居多,tty这玩意见的不多,当时也没在意,就把这两者弄混了。其实shell更多的是指执行命令的程序,一个用户用来操作系统的入口,而terminal则是指的我们见到的黑框框这个界面本身。

​ 不知道大家有没有一个疑惑,就是为什么我们的命令行是怎么将我们的键盘输入显示在界面上的,其实这一步就是终端做的,终端是一个用于捕捉用户的输入,还有光标的移动等等的处理程序,而shell是用于执行命令的程序,也就是说,当你敲下回车的时候,终端将你输入的这一行内容交给shell来执行,并将shell的输出显示在终端中。

现在我们知道,终端干的活儿是从用户这里接收输入(键盘、鼠标等输入设备),扔给 Shell,然后把 Shell 返回的结果展示给用户(比如通过显示器)。而 Shell 干的活儿是从终端那里拿到用户输入的命令,解析后交给操作系统内核去执行,并把执行结果返回给终端。

​ 当然实际情况更加复杂,大家可以看推荐的那篇文章。

web终端

​ 知道了终端和shell的区别了之后,我就明白了为什么git指令会进入静默模式。那么我们首先就是要去找一个终端仿真器(terminal emulator),github上有很多大神写的终端仿真器,我得要求是能在web里面运行的,远程的。最终我找到了两个库——xtermhterm,有一篇文章比较了两个库的优劣。我还并没有决定使用哪个库。

​ 用库不是重点,重点是我依然没有弄明白怎么打开一个终端,这带来的最大的一个问题就是,我无法自己写代码来实现自己的程序(用websocket或者其他的手段将远程的终端映射到浏览器里面),我只能用别人写好的,这当然不行,大家都用的websocket协议,但是就像我上篇文章写到的,阿里云的API网关对websocket协议的通讯做了一大堆的包装,github上的程序都不满足我的需求。直到我看到了一段代码

或者还有这段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func open() (pty, tty *os.File, err error) {
	p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
	if err != nil {
		return nil, nil, err
	}

	sname, err := ptsname(p)
	if err != nil {
		return nil, nil, err
	}

	err = unlockpt(p)
	if err != nil {
		return nil, nil, err
	}

	t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
	if err != nil {
		return nil, nil, err
	}
	return p, t, nil
}

这让我明白了一些东西,就是我原先就知道的,linux里面任何设备都是一个文件,所以其实终端(terminal)作为一个古老的设备,其在linux的表现一定会是一个文件。第一步就走出来了,所以我如果想打开一个终端,我只需要打开这个设备文件就好了。

​ 今天先写到这里,主要是我还没有写这个程序,但是经过我查了这么多资料,程序大概怎么写我已经明白了,剩下的就是在写代码的过程中继续深挖了。我有预感这个程序会大大的增加我对计算机的认识,过程很艰难,希望这个程序能走下去。