Files
blog/_posts/2026-08-01-terminal.md
mayx 89a0af5632 Update 5 files
- /_data/other_repo_list.csv
- /_posts/2026-08-01-terminal.md
- /index.html
- /_tools/envs_post-receive
- /games.md
2026-07-31 16:00:40 +00:00

31 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
layout: post
title: 一次制作终端版博客的经历
tags: [WASM, 终端, Linux, 博客]
---
在浏览器上用真的Linux访问博客会是什么样的感觉<!--more-->
# 起因
在去年的时候我为了想在博客上加个终端,写过一篇关于[在浏览器中运行Linux](/2025/12/01/linux.html)的文章。不过那时候只是调查了有哪些可能的方法,并没有真的做出来,主要是自己做感觉太麻烦了😂。
但从上次进行了[Vibe Coding](/2026/07/01/vibe-coding.html)之后我意识到这可能不再是什么麻烦事也许只要和AI聊聊天就能轻松做出来了于是接着之前的方案我开始着手完成我的想法。
# 终端版博客的不同形式
## 基于WASM Linux的版本
在之前的文章里我其实更倾向于WASM Linux的方案尤其是[Thomas Stokes](https://github.com/tombl)制作的[WASM Linux](https://github.com/tombl/linux)因为它相比于虚拟机更轻量效率更高而且还能完美地在Safari中运行毕竟我用的是macOS😂因此接下来我计划用它为基础制作我的终端版博客。
不过之前我也说过目前这个WASM Linux还不能和外界通信不能和外界通信就不能读取我的文章。于是我打算先让AI解决这个问题。但如果我直接给它说想要和外界通信也许它会给我整一堆奇怪的实现所以我得自己先想一个实现起来最简单的方案。之前我记得Fabrice Bellard大神写的JSLinux中有一个剪贴板设备文件可以和外部通信那么干脆让AI写一个能在浏览器中执行JS的设备文件吧这样做出来只需要写简单的Shell脚本就可以和浏览器交互了也不需要考虑如何编译WASM程序于是就这样我开始让它实现这个功能。
最终经过几次调试和修改之后AI真的把这个设备文件给做出来了不过刚做出来的时候有些问题。因为在这个Linux中的进程都是在Web Worker中运行执行的JS也会在Web Worker中运行。但是Web Worker的局限性很大并不能和当前网页进行交互不过这种问题也都是小事发现了之后只要给AI一反馈也是轻轻松松就改好了……最终实现的效果我感觉相当不错既然如此那我就把AI做的这个驱动给上游[PR](https://github.com/tombl/linux/pull/24)一下吧,也算做个贡献。不过最终原作者不太喜欢这种实现方式,他好像更喜欢标准化的方式,说是已经做了一个[VsockDevice](https://github.com/tombl/linux/blob/b36416c7f266a465361ab7dde7622eb37239cd7e/tools/wasm/src/virtio.ts#L354)可以直接使用Linux自带的驱动和外界通信所以把我的PR拒了看来AI Slop还是入不了大佬的法眼😂~~不过我问了一下AI它说用这个设备的话可能需要`ioctl()`系统调用就没办法直接用Shell操作了只能用别的语言写的程序才能用它通信所以我只好自己用这种不标准的方式了。~~ 虽然VsockDevice确实是不太好操作但是大佬随后又新增了一个ethernetDevice可以用来上网考虑到维护自己的分支实在是太麻烦了所以我让AI写了一个虚拟的HTTP服务使其能够执行JS顺便还增加了连接互联网的功能。这样我就可以直接使用上游的代码不需要再维护之前写的驱动了其实以太网比Vsock复杂多了只是因为可以用wget之类的客户端请求所以才简单😋
在做好与外界通信的通道后我就开始让AI写能和我博客交互的脚本不过在这个过程中也遇到了不少问题最开始的时候发现这个Shell的管道有些问题执行的时候会忽略管道前的命令后面的命令就没法执行了……感觉有点奇怪所以我要求它在实现交互脚本时不要使用管道符。除此之外我还发现反引号和`$()`这些能把执行结果插入字符串的语法也不能用……总之就是局限相当多,但它还是克服了这些困难最终把脚本给写出来了,最终实现了列出文章、查看文章、打开文章和查看评论等功能,效果还是相当不错。 ~~唯一的缺陷就是它不能进行异步操作,只能同步请求,所以在进行请求的时候会把浏览器卡住,体验稍有打折。~~ 后来用了网络版的JS执行服务后就可以异步了避免出现把浏览器卡住的情况。
不过这个系统如果管道符不能用的话效果会差一大截这可是Shell的灵魂啊所以我提交了一个[Issue](https://github.com/tombl/linux/issues/25)希望作者能修一下。结果作者真的强得离谱提出问题之后第二天就修复了实在是太强了😨。但修好这个问题之后作者又整了一堆别的花活把内存限制给取消了结果我在Safari上一运行就报OOM的错误……于是我把这个问题又[反馈](https://github.com/tombl/linux/pull/26#issuecomment-5018155963)了一下顺便让AI看看这个问题怎么解决结果AI也不辜负我的期待轻轻松松就解决了🤣。最终我除了会提出问题之外什么也不会做只能看着大佬和AI完成我的想法了😝。
后来增加的以太网网关也挺折腾原理其实并不复杂但直接给AI说想用这个接口上网的时候它会自己想办法搓一套漏洞百出的TCP/IP协议栈所以后来我在GitHub找了个[tcpip.js](https://github.com/chipmk/tcpip.js)库让它集成BUG就比它自己手搓的少了不少。后来我又想加一个TLS终止功能因为在浏览器上没办法直接让系统里的程序发送原始的TLS数据包去请求网站但我又希望它能够请求带有https协议的网址所以要提前对TLS进行解密再转换成`fetch()`这时候我就没让AI自己手搓了在网上找了个[node-forge](https://github.com/digitalbazaar/forge)库让AI对接就可以避免出现一堆奇怪的BUG了。
做好网关之后我又突发奇想想做一个展示终端内状态的页面但是目前JS并不能主动和里面的系统直接通信所以又让AI搓了一个通过Service Worker访问系统内网络服务的功能然后用busybox的httpd执行sh写的cgi程序就可以被前端读取到了。随后我还给原作者发了个[Issue](https://github.com/tombl/linux/issues/34)展示这个Service Worker的效果结果人家已经做了这个功能我还是太Naive了😂。
最终做好的网站可以在[这里](https://mabbs.github.io/linux/)查看效果真的不是一般的好相比于其他模仿终端形式的博客简直是降维打击毕竟这是真的Linux啊虽然目前依然有些BUG但是原作者修BUG的速度还是挺快的相信等他发布正式版之后体验会更进一步。
## 基于JSNix的版本
虽然我觉得追求真实感很重要,但是我又回去看了一下为我提供想法的[JSNix](https://github.com/Erzbir/jsnix)。虽然这个项目并不是真的Linux但是我让AI看了一遍之后它对这个项目的评价也很高说是作者对Linux的了解非常深入很多细节模拟的也非常到位。而且为WASM Linux制作的那些脚本在这个JSNix上其实完全可以实现还更简单于是我直接让AI参考给WASM Linux写的脚本把那些功能全部移植到这个JSNix上。也许是因为AI更擅长编写网页很快它就完成了这些功能而且效果非常不错基本上和WASM Linux上面的效果一样表现也相当不错最终生成的结果可以在[这里](https://mabbs.github.io/jsnix/)查看。
不过假的毕竟还是假的和真的Linux差异还是有不少的像正经的Shell可以在终端中直接用if、for和while之类的语法写一些东西它这个就必须要编写成脚本才可以而且解析也有相当多的问题。各种命令的运行结果很多都是硬编码的只是编了一段对应命令的输出参数做得也不全。另外著名的Linux文本三剑客grep、sed和awk在这个系统里实现得也非常差只做了一些非常基础的功能基本上就是完全不可用。所以说这个系统还是不够真实只能做最基础的体验不能够深究。
但并不是说它没有优点它作为纯粹的JS不像WASM Linux那样容易出现兼容性问题比如很多手机浏览器不支持跨源隔离导致SharedArrayBuffer之类的API没法用所以手机上只能体验这个JSNix的版本另外WASM Linux的体积虽然说并不算很大但也有好几MiB不像这个JSNix连1MiB都不到还有这个系统没有启动过程相比于WASM Linux来说加载更快而且在编写和修改功能的时候比WASM Linux简单不少像给WASM Linux做的终端状态展示在JSNix上根本不需要折腾什么Service Worker以及请求网络之类的也非常简单直接`fetch()`就可以也正是如此JSNix的版本AI没一会儿就做完了……总之就是只要不涉及具体功能方面JSNix都比WASM Linux要强不少不过这样说有点“抛开事实不谈”的感觉了😂。
# 感想
最终做出来的这两个版本的终端版博客基本上所有的代码都不是我写的真的做到了仅仅是和AI聊聊天就把东西做出来了……只能说AI现在真的不是一般的强啊当然方案还是得自己考虑因为AI一旦走错了方向就很容易往一个方向不停地钻结果就是花了很长时间可能效果会很差尤其是现在的AI还特别喜欢自己造轮子所以这时候还是自己找找看已经有的方案然后告诉它会比较好。
从效果来说这次写的东西也让我非常满意,我想我这次做的这个博客界面估计是前所未有的,毕竟这可是在浏览器上用**真的**Linux访问博客啊其他人做的都是假的。至于虚拟机那些方案可能也是因为太重所以基本上没人用而WASM Linux只有Thomas Stokes做的效果最好但是又没有受到应有的关注……总之从我个人的角度来看这次做的东西还挺Cool就是不知道会不会吸引其他人来看呢……可能还是太小众了吧😂。