This commit is contained in:
2025-12-31 16:00:29 +00:00
commit 3688f93d5d
310 changed files with 93400 additions and 0 deletions

360
2025/12/01/linux.html Normal file
View File

@@ -0,0 +1,360 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>在浏览器中运行Linux的各种方法 | Mayx的博客</title>
<meta name="generator" content="Jekyll v3.9.5" />
<meta property="og:title" content="在浏览器中运行Linux的各种方法" />
<meta name="author" content="mayx" />
<meta property="og:locale" content="zh_CN" />
<meta name="description" content="浏览器已经无所不能了!" />
<meta property="og:description" content="浏览器已经无所不能了!" />
<meta property="og:site_name" content="Mayx的博客" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2025-12-01T00:00:00+08:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="在浏览器中运行Linux的各种方法" />
<meta name="google-site-verification" content="huTYdEesm8NaFymixMNqflyCp6Jfvd615j5Wq1i2PHc" />
<meta name="msvalidate.01" content="0ADFCE64B3557DC4DC5F2DC224C5FDDD" />
<meta name="yandex-verification" content="fc0e535abed800be" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"mayx"},"dateModified":"2025-12-01T00:00:00+08:00","datePublished":"2025-12-01T00:00:00+08:00","description":"浏览器已经无所不能了!","headline":"在浏览器中运行Linux的各种方法","mainEntityOfPage":{"@type":"WebPage","@id":"/2025/12/01/linux.html"},"publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://avatars0.githubusercontent.com/u/17966333"},"name":"mayx"},"url":"/2025/12/01/linux.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="canonical" href="https://mabbs.github.io/2025/12/01/linux.html" />
<link type="application/atom+xml" rel="alternate" href="/atom.xml" title="Mayx的博客" />
<link rel="alternate" type="application/rss+xml" title="Mayx的博客(RSS)" href="/rss.xml" />
<link rel="alternate" type="application/json" title="Mayx的博客(JSON Feed)" href="/feed.json" />
<link rel="stylesheet" href="/assets/css/style.css?v=1767196818" />
<!--[if !IE]> -->
<link rel="stylesheet" href="/Live2dHistoire/live2d/css/live2d.css" />
<!-- <![endif]-->
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Mayx的博客" />
<link rel="webmention" href="https://webmention.io/mabbs.github.io/webmention" />
<link rel="pingback" href="https://webmention.io/mabbs.github.io/xmlrpc" />
<link rel="preconnect" href="https://summary.mayx.eu.org" crossorigin="anonymous" />
<link rel="prefetch" href="https://www.blogsclub.org/badge/mabbs.github.io" as="image" />
<link rel="blogroll" type="text/xml" href="/blogroll.opml" />
<link rel="me" href="https://github.com/Mabbs" />
<script src="/assets/js/jquery.min.js"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<script>
var lastUpdated = new Date("Thu, 01 Jan 2026 00:00:18 +0800");
var BlogAPI = "https://summary.mayx.eu.org";
</script>
<script src="/assets/js/main.js"></script>
<!--[if !IE]> -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-137710294-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-137710294-1');
</script>
<script src="/assets/js/instant.page.js" type="module"></script>
<!-- <![endif]-->
</head>
<body>
<!--[if !IE]> --><noscript><marquee style="top: -15px; position: relative;"><small>发现当前浏览器没有启用JavaScript这不影响你的浏览但可能会有一些功能无法使用……</small></marquee></noscript><!-- <![endif]-->
<!--[if IE]><marquee style="top: -15px; position: relative;"><small>发现当前浏览器为Internet Explorer这不影响你的浏览但可能会有一些功能无法使用……</small></marquee><![endif]-->
<div class="wrapper">
<header class="h-card">
<h1><a class="u-url u-uid p-name" rel="me" href="/">Mayx的博客</a></h1>
<img src="https://avatars0.githubusercontent.com/u/17966333" fetchpriority="high" class="u-photo" alt="Logo" style="width: 90%; max-width: 300px; max-height: 300px;" />
<p class="p-note">Mayx's Home Page</p>
<form action="/search.html">
<input type="text" name="keyword" id="search-input-all" placeholder="Search blog posts.." />&#160;<input type="submit" value="搜索" />
</form>
<br />
<p class="view"><a class="u-url" href="/Mabbs/">About me</a></p>
<ul class="downloads">
<li style="width: 270px; border-right: none;"><a href="/MayxBlog.tgz">Download <strong>TGZ File</strong></a></li>
</ul>
</header>
<section class="h-entry">
<small><time class="date dt-published" datetime="2025-12-01T00:00:00+08:00">1 December 2025</time> - 字数统计4403 - 阅读大约需要13分钟 - Hits: <span id="/2025/12/01/linux.html" class="visitors">Loading...</span></small>
<h1 class="p-name">在浏览器中运行Linux的各种方法</h1>
<p class="view">by <a class="p-author h-card" href="//github.com/Mabbs">mayx</a></p>
<div id="outdate" style="display:none;">
<hr /><p>
这是一篇创建于 <span id="outime"></span> 天前的文章,其中的信息可能已经有所发展或是发生改变。
</p>
</div>
<script>
daysold = Math.floor((new Date().getTime() - new Date("Mon, 01 Dec 2025 00:00:00 +0800").getTime()) / (24 * 60 * 60 * 1000));
if (daysold > 90) {
document.getElementById("outdate").style.display = "block";
document.getElementById("outime").innerHTML = daysold;
}
</script>
<hr />
<b>AI摘要</b>
<p id="ai-output">这篇文章介绍了在浏览器中运行Linux的各种方法从最初的纯JS虚拟机JSLinux到后来的WASM虚拟机如v86、WebVM、WebCM再到容器化方案container2wasm以及直接将Linux内核编译为WASM的方案。作者详细对比了这些方案的优缺点包括性能、兼容性、功能和开发难度。文章还提到了模仿Linux环境的WebContainers和JupyterLite并最终认为虚拟机方案更靠谱但对WASM的未来充满期待。作者最后表示博客上添加类似功能的计划还在考虑中目前主要分享了各种方法的探索过程。</p>
<hr />
<ul><li><a href="#起因">起因</a></li><li><a href="#在浏览器中运行linux">在浏览器中运行Linux</a><ul><li><a href="#虚拟机方案">虚拟机方案</a><ul><li><a href="#纯js虚拟机">纯JS虚拟机</a></li><li><a href="#wasm虚拟机">WASM虚拟机</a></li></ul></li><li><a href="#纯wasm方案">纯WASM方案</a></li><li><a href="#模仿的linux">模仿的Linux</a></li></ul></li><li><a href="#总结">总结</a></li></ul>
<hr />
<main class="post-content e-content" role="main"><p>浏览器已经无所不能了!<!--more--></p>
<h1 id="起因">
<a href="#起因"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 起因
</h1>
<p>前段时间跟网友交流时有人展示了他博客里的一个Linux终端模拟项目<a href="https://github.com/Erzbir/jsnix">jsnix</a>看起来挺有意思的里面甚至还藏了一个CTF。不过我感觉他这个终端和博客本身并没有真正联动起来本质上只是一个模拟了Linux Shell行为的交互界面。除此之外我还发现了另一个风格类似的<a href="https://github.com/Luyoung0001/myWebsite">个人主页</a>它虽然也走了终端风格但功能更简单还原度也不算高。不过它至少和博客内容做了一些基础联动——尽管目前也只是做到列出文章这种程度😂当然有这类功能的博客应该也不少只是我发现的不太多……于是我就想不如我也给自己的博客加一个类似的“命令行访问”功能应该会很有趣。当然如果真要做的话我肯定不会满足于只实现几个模拟指令——既然要做就要追求真实感至少得在浏览器上运行真实的Linux终端才不会让人觉得出戏吧😋。</p>
<h1 id="在浏览器中运行linux">
<a href="#在浏览器中运行linux"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 在浏览器中运行Linux
</h1>
<h2 id="虚拟机方案">
<a href="#虚拟机方案"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 虚拟机方案
</h2>
<h3 id="纯js虚拟机">
<a href="#纯js虚拟机"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 纯JS虚拟机
</h3>
<p>要说到在浏览器上运行Linux最先想到的应该就是<a href="https://bellard.org">Fabrice Bellard</a>大神写的<a href="https://bellard.org/jslinux/">JSLinux</a>这可能是第一个在浏览器中实现的虚拟机毕竟是最强虚拟机QEMU的作者编写的。现在他的个人主页中展示的这个版本是WASM版本而他最早写的是纯JS实现的。那个JS实现的版本现在在GitHub上有一个<a href="https://github.com/levskaya/jslinux-deobfuscated">去混淆的版本</a>可以用作学习和研究于是我顺手Fork了一份在GitHub Pages上部署作为<a href="http://mabbs.github.io/jslinux/">演示</a></p><p>
作为纯JS实现的x86虚拟机性能估计是最差的但相应的兼容性也最好在Bellard当年写JSLinux的时候还没有WASM这种东西呢所以即使是在不支持WASM的IE11中也可以正常运行。假如我想把它作为终端用在我的博客上似乎也是个不错的选择即使我完全看不懂代码不知道如何实现JS和虚拟机的通信它也预留了一个剪贴板设备可以让我轻松地做到类似的事情比如我在里面写个Bash脚本通过它和外面的JS脚本联动来读取我的文章列表和内容那也挺不错。 </p><p>
当然Bellard用纯JS编写虚拟机也不是独一份他实现了x86的虚拟机相应的也有人用纯JS实现了RISC-V的虚拟机比如<a href="https://github.com/riscv-software-src/riscv-angel">ANGEL</a>,看起来挺不错,所以同样也顺手<a href="https://mabbs.github.io/riscv-angel/">搭了一份</a>。只不过它似乎用了一些更先进的语法至少IE11上不能运行。 </p><p>
另外还有一个比较知名的项目,叫做<a href="https://github.com/s-macke/jor1k">jor1k</a>它模拟的是OpenRISC架构。只是这个架构目前已经过时基本上没什么人用了不过这里面还内置了几个演示的小游戏看起来还挺有意思。 </p><p>
除了这些之外其实能在浏览器上运行的Linux也不一定是个网页有一个叫做<a href="https://github.com/ading2210/linuxpdf">LinuxPDF</a>的项目可以让Linux运行在PDF中它的原理和JSLinux差不多所以需要PDF阅读器支持JS看它的介绍貌似只能在基于Chromium内核的浏览器中运行而且因为安全问题在PDF中有很多功能不能用所以它的速度甚至比JSLinux还要慢功能还很少因此它基本上只是个PoC没什么太大的意义。</p>
<h3 id="wasm虚拟机">
<a href="#wasm虚拟机"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> WASM虚拟机
</h3>
<p>那还有别的方案吗既然Bellard都选择放弃纯JS的JSLinux而选择了WASM显然还有其他类似的项目比如<a href="https://github.com/copy/v86">v86</a>这也是一个能在浏览器中运行的x86虚拟机不过因为使用了WASM和JIT技术所以效率要比纯JS的JSLinux高得多。另外作为虚拟机自然是不止能运行Linux其他的系统也能运行在示例中除了Linux之外还有DOS和Windows之类的系统功能还挺强大如果能自己做个系统镜像在博客里运行似乎也是不错的选择。 </p><p>
另外还有一个相对比较知名的叫<a href="https://github.com/leaningtech/webvm">WebVM</a>从效果上来说和v86几乎没有区别同样使用了WASM和JIT技术也都只支持32位x86然而它的虚拟化引擎CheerpX是闭源产品既然和v86都拉不开差距不知道是谁给他们的信心把它作为闭源产品😅。不过看它的说明文档其相比于v86的主要区别是实现了Linux系统调用考虑到它不能运行其他操作系统而且Linux内核也不能更换那我想它可能是类似于WSL1的那种实现方案也许性能上会比v86好一些吧……只不过毕竟是闭源产品不太清楚具体实现了。 </p><p>
既然纯JS有RISC-V的虚拟机WASM当然也有比如<a href="https://github.com/edubart/webcm">WebCM</a>。这个项目相比于其他的项目有个不太一样的地方它把虚拟机、内核以及镜像打包成了一个单独的WASM文件……只是这样感觉并没有什么好处吧改起来更加复杂了。 </p><p>
以上这些虚拟机方案各有不同,但是想做一个自己的镜像相对来说还是有点困难,于是我又发现了另一个项目:<a href="https://github.com/container2wasm/container2wasm">container2wasm</a>它可以让一个Docker镜像在浏览器中运行当然实际实现其实和Docker并没有什么关系本质还是虚拟机只是制作镜像的时候可以直接用Docker镜像方便了不少但Docker镜像一般也都很大所以第一次加载可能要下载很长时间。另外它还有一个优势可以使用<a href="https://bochs.sourceforge.io/">Bochs</a>运行x86_64的镜像不像v86和WebVM只能模拟32位的x86虽然Bochs的运行效率可能会差一些而且可以使用WASI直接访问网络不像以上几个项目如果需要访问网络需要用到中继服务。当然访问网络这个还是要受浏览器本身的跨域策略限制。总之从项目本身来说感觉也算是相当成熟了尤其能用Docker镜像的话……我甚至可以考虑直接用<a href="https://hub.docker.com/r/unmayx/mabbs">镜像</a>在线演示我曾经的<a href="https://github.com/Mabbs/Mabbs.Project">Mabbs</a>项目😋。</p>
<h2 id="纯wasm方案">
<a href="#纯wasm方案"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 纯WASM方案
</h2>
<p>其实想要在浏览器中运行Linux也不一定非得要用虚拟机用虚拟机相当于是把其他指令集的机器码翻译为WASM然后浏览器还得再翻译成宿主机CPU支持的指令集然而WASM本身其实也算是一种指令集各种编译型语言编写的程序也能编译出WASM的产物比如<a href="https://github.com/ffmpegwasm/ffmpeg.wasm">FFmpeg</a>。所以Linux内核也完全可以被编译成WASM正好前段时间我看新闻说<a href="https://github.com/joelseverin">Joel Severin</a>做了这么一个<a href="https://github.com/joelseverin/linux-wasm">项目</a>对Linux内核做了一些修改使其可以被编译为WASM程序我试了一下貌似在Safari浏览器中不能正常工作……Chrome浏览器倒是没问题不过即使这样用起来BUG也很多随便执行几条命令就会冻结体验不是很好。 </p><p>
沿着这个项目,我又找到一个由<a href="https://github.com/tombl">Thomas Stokes</a>制作的<a href="https://github.com/tombl/linux">项目</a>和Joel的项目差不多但我测了一下可以在Safari上运行感觉这个项目更完善不过之前那个项目上了新闻所以⭐数比这个更高😂。 </p><p>
于是我把它复制了一份在我的GitHub Pages上<a href="https://mabbs.github.io/linux/">部署</a>但直接用仓库中的源代码会显示“Error: not cross origin isolated”然而在Thomas自己部署的网站中可以正常打开我看了一眼貌似是因为在GitHub Pages中没有<a href="https://web.dev/articles/coop-coep">COOP和COEP响应头</a>导致的。Linux作为多任务操作系统来说当然要运行多个进程而Linux要管理它们就需要跨线程Web Worker读取内存的能力所以用到了SharedArrayBuffer对象。不过由于CPU曾经出过“幽灵”漏洞导致现代浏览器默认禁止使用SharedArrayBuffer对象除非在服务器中配置COOP和COEP响应头才可以用但是Joel的项目也是在GitHub Pages上运行的啊为什么可以正常运行看了源代码后才发现原来可以<a href="/2025/08/01/sw-proxy.html">用Service Worker作为反向代理</a>来给请求的资源加上响应头,他使用的是<a href="https://github.com/gzuidhof/coi-serviceworker">coi-serviceworker</a>这个项目,所以我也给我部署的代码中加上了这个脚本,总算是解决了这个问题。 </p><p>
部署好这个项目之后我试用了几下虽然有些操作仍然会导致系统冻结但相比Joel的版本来说已经好多了。很遗憾的是目前这个WASM Linux还不能和外界通信所以作用不是很大另外如果想在里面运行其他二进制程序还是相当困难首先在WASM中不存在内存管理单元MMU不能实现隔离和分页的功能另外以WASM作为指令集的环境下编译的产物也得是WASM所以目前来说想用它做点什么还是不太合适。 </p><p>
以上的这两个将Linux内核编译为WASM的方案其实相当于给内核打补丁然后把浏览器看作是虚拟机来运行有点像Xen不过还有一种让Linux原生运行在WASM的<a href="https://github.com/okuoku/wasmlinux-project">项目</a>,它将<a href="https://github.com/lkl/linux">Linux kernel library</a>编译为了WASM。那么什么是LKL简单来说它有点像Wine就和我之前所说的<a href="/2024/12/08/simulator.html">OS模拟器</a>差不多可以提供一个环境让程序以为自己在Linux下运行所以说它和之前的实现有一些不一样它不存在内核模式更像是一个普通的程序而不是系统了。 </p><p>
不过这个项目的体验也比较一般,它无论做什么都得按两次回车,看说明的意思貌似是因为没有实现异步信号传递,所以要手动打断<code class="language-plaintext highlighter-rouge">read</code>函数而且也经常莫名其妙卡住总体体验不如Thomas的项目。</p>
<h2 id="模仿的linux">
<a href="#模仿的linux"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 模仿的Linux
</h2>
<p>其实如果只是想做到和Linux类似的功能也有这样的项目比如<a href="https://github.com/stackblitz/webcontainer-core">WebContainers</a>它没有运行Linux系统但是模拟了一个环境可以在浏览器中运行Node.js以及Python之类的脚本而且让脚本以为自己在Linux中运行除此之外它还能用Service Worker把环境中运行的端口映射给浏览器可以算是真的把服务端跑在浏览器上了。这个技术还挺高级不过想想也挺合理毕竟有WASI直接编译为WASM的程序也不需要操作系统就能运行所以用WASM去运行Linux本来就有点多此一举了😂。不过很遗憾的是WebContainers也不是开源软件要使用它只能引入StackBlitz的资源而且全网完全没有开源的替代品……也许在浏览器上进行开发本来就是个伪需求所以没什么人实现吧。 </p><p>
当然如果只是实现和WebContainers类似的功能<a href="https://github.com/jupyterlite/jupyterlite">JupyterLite</a>也可以实现它可以在浏览器中像使用本地JupyterLab那样运行JS和Python还能用Matplotlib、Numpy、Pandas进行数据处理功能可以说非常强大而且还是开源软件。只不过它没有模拟操作系统的环境所以不能运行Node.js项目也不能提供终端所以不太符合我想要的效果……</p>
<h1 id="总结">
<a href="#总结"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 总结
</h1>
<p>总的来说如果想要在博客上搞Linux终端目前来看似乎虚拟机方案会更靠谱一些虽然相对来说效率可能比较低但毕竟目前WASM方案的可靠性还是不够而且考虑到还需要配置额外的响应头感觉有点麻烦当然我觉得WASM还是算未来可期的如果成熟的话肯定还是比虚拟机要更好一些毕竟没有转译性能肯定要好不少。至于WebContainers这种方案……等什么时候有开源替代再考虑吧需要依赖其他服务感觉不够可靠。只是也许我的想法只需要模拟一个合适的文件系统然后给WASM版的Busybox加个终端就够了不过这样感觉Bug会更多😂。 </p><p>
至于打算什么时候给博客加上这个功能应该也是未来可期吧😝目前还没什么好的思路仅仅是分享一下在浏览器中运行Linux的各种方法。</p></main>
<small style="display: block">tags: <a rel="category tag" class="p-category" href="/search.html?keyword=%E6%B5%8F%E8%A7%88%E5%99%A8"><em>浏览器</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=Linux"><em>Linux</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=%E8%99%9A%E6%8B%9F%E6%9C%BA"><em>虚拟机</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=WASM"><em>WASM</em></a> <span style="float: right;"><a href="https://gitlab.com/mayx/mayx.gitlab.io/tree/master/_posts/2025-12-01-linux.md">查看原始文件</a></span></small>
<h4 style="border-bottom: 1px solid #e5e5e5;margin: 2em 0 5px;">推荐文章</h4>
<p id="suggest-container">Loading...</p>
<script>
var suggest = $("#suggest-container");
$.get(BlogAPI + "/suggest?id=/2025/12/01/linux.html&update=" + lastUpdated.valueOf(), function (data) {
if (data.length) {
getSearchJSON(function (search) {
suggest.empty();
var searchMap = {};
for (var i = 0; i < search.length; i++) {
searchMap[search[i].url] = search[i];
}
var tooltip = $('<div class="content-tooltip"></div>').appendTo('body').hide();
for (var j = 0; j < data.length; j++) {
var item = searchMap[data[j].id];
if (item) {
var link = $('<a href="' + item.url + '">' + item.title + '</a>');
var contentPreview = item.content.substring(0, 100);
if (item.content.length > 100) {
contentPreview += "……";
}
link.hover(
function(e) {
tooltip.text($(this).data('content'))
.css({
top: e.pageY + 10,
left: e.pageX + 10
})
.show();
},
function() {
tooltip.hide();
}
).mousemove(function(e) {
tooltip.css({
top: e.pageY + 10,
left: e.pageX + 10
});
}).data('content', contentPreview);
suggest.append(link);
suggest.append(' - ' + item.date + '<br />');
}
}
});
} else {
suggest.html("暂无推荐文章……");
}
});
</script>
<br />
<div class="pagination">
<span class="prev">
<a href="/2025/11/01/mirrors.html">
上一篇:让博客永恒的探索
</a>
</span>
<br />
<span class="next">
<a href="/2026/01/01/summary.html">
下一篇:年终总结
</a>
</span>
</div>
<!--[if !IE]> -->
<link rel="stylesheet" href="/assets/css/gitalk.css">
<script src="/assets/js/gitalk.min.js"></script>
<div id="gitalk-container"></div>
<script>
var gitalk = new Gitalk({
clientID: '36557aec4c3cb04f7ac6',
clientSecret: 'ac32993299751cb5a9ba81cf2b171cca65879cdb',
repo: 'mabbs.github.io',
owner: 'Mabbs',
admin: ['Mabbs'],
id: '/2025/12/01/linux', // Ensure uniqueness and length less than 50
distractionFreeMode: false, // Facebook-like distraction free mode
proxy: "https://cors-anywhere.mayx.eu.org/?https://github.com/login/oauth/access_token"
})
gitalk.render('gitalk-container')
</script>
<!-- <![endif]-->
</section>
<!--[if !IE]> -->
<div id="landlord" style="left:5px;bottom:0px;">
<div class="message" style="opacity:0"></div>
<canvas id="live2d" width="500" height="560" class="live2d"></canvas>
<div class="live_talk_input_body">
<form id="live_talk_input_form">
<div class="live_talk_input_name_body" >
<input type="checkbox" id="load_this" />
<input type="hidden" id="post_id" value="/2025/12/01/linux.html" />
<label for="load_this">
<span style="font-size: 11px; color: #fff;">&#160;想问这篇文章</span>
</label>
</div>
<div class="live_talk_input_text_body">
<input name="talk" type="text" class="live_talk_talk white_input" id="AIuserText" autocomplete="off" placeholder="要和我聊什么呀?" />
<button type="submit" class="live_talk_send_btn" id="talk_send">发送</button>
</div>
</form>
</div>
<input name="live_talk" id="live_talk" value="1" type="hidden" />
<div class="live_ico_box" style="display:none;">
<div class="live_ico_item type_info" id="showInfoBtn"></div>
<div class="live_ico_item type_talk" id="showTalkBtn"></div>
<div class="live_ico_item type_music" id="musicButton"></div>
<div class="live_ico_item type_youdu" id="youduButton"></div>
<div class="live_ico_item type_quit" id="hideButton"></div>
<input name="live_statu_val" id="live_statu_val" value="0" type="hidden" />
<audio src="" style="display:none;" id="live2d_bgm" data-bgm="0" preload="none"></audio>
<input id="duType" value="douqilai" type="hidden" />
</div>
</div>
<div id="open_live2d">召唤伊斯特瓦尔</div>
<!-- <![endif]-->
<footer>
<p>
<small>Made with ❤ by Mayx<br />Last updated at 2026-01-01 00:00:18<br /> 总字数614622 - 文章数178 - <a href="/atom.xml" >Atom</a> - <a href="/README.html" >About</a></small>
</p>
</footer>
</div>
<script src="/assets/js/scale.fix.js"></script>
<!--[if !IE]> -->
<script src="/assets/js/main_new.js"></script>
<script src="/Live2dHistoire/live2d/js/live2d.js"></script>
<script src="/Live2dHistoire/live2d/js/message.js"></script>
<!-- <![endif]-->
</body>
</html>