NodeOS:基于 JavaScript 的操作系统
已发表: 2022-03-11我相信大多数程序员都听说过 Node.js,但是 NodeOS 呢? 是的,NodeOS,一个用 Node.js 编写的操作系统。 嗯,有点。 NodeOS 将 Linux 内核用于大多数性能关键的事情,例如硬件交互,但对于其他所有事情,它都使用 Node.js。 NodeOS 的开发始于两年前,由一群共享一个简单但有趣的想法的人创建: “是否可以仅使用 Node.js 创建操作系统?”
有什么大不了的?
首先,想想 Node.js 在它出现的短时间内所取得的进步。 现在,想想操作系统发生的同样的事情。 然后,让我们添加一些很酷的东西。
每个用户独立和隔离的根文件系统
NodeOS 引入了一个有趣的范例:如果所有用户都有一个独立的文件系统,它会给他们一个简单的文件系统层次结构来使用。 由于他们的“主文件夹”实际上是他们自己的文件系统层次结构的根目录,因此他们可以在不需要特殊权限的情况下全局安装包,也不需要配置任何东西,因为它们默认安装在他们的主目录中。 此外,它还提供了很好的安全性; 如果黑客找到了进入操作系统中特定帐户的方法,那么他/她可以访问的唯一分区就是该用户的分区。 最终结果是黑客无法破坏整个系统。
Node.js 和 NPM
如果您考虑一下,使用 Node.js 的操作系统意味着 NPM 中可用的任何包同时也是 NodeOS 包。 在撰写本文时,有 210,735 个包; 由于 NPM 包的数量每分钟都在增长,如果几年后 NodeOS 拥有一百万个应用程序也就不足为奇了。
它基于Linux内核
这似乎没什么大不了的,但 Linux 是最常用的服务器操作系统。 由于 NodeOS 基于 Linux 内核,您可以运行为其他 Linux 发行版编写的每个应用程序,只需进行极少的更改。
缺点
尽管我想要一个完整的 NodeOS,但它还没有。 它仍然缺少服务器操作系统的许多关键功能。 例如,缺少整个 BASH 工具集,包括 ps、tail、nano 和 grep。 此外,您不能将其作为桌面操作系统运行,因为它没有 GUI。 当然,您可以使用一些 JavaScript 相当轻松地实现一些缺失的功能,但事实上所有提到的功能在默认情况下都不可用,这并不好。
那么,我该如何试用 NodeOS?
使用 Docker
试用 NodeOS 最简单快捷的方法是使用以下方法:
- 一台装有 Mac OSX 或 Linux 的计算机。 它可能适用于 Windows,但我没有尝试过。
- 码头工人。
安装 Docker 后,运行 NodeOS 实例就很容易了。 您需要做的就是执行以下命令,Docker 会做所有的事情:
sudo docker run -t -i nodeos/nodeos
当您运行上述命令时,Docker 会自动从存储库下载 NodeOS 的磁盘映像,并在虚拟机中执行 NodeOS 的安装。 安装完成后,它会打开一个到 NodeOS shell 的 SSH 会话。
没有码头工人
有一些原因可以避免使用 Docker,其中一个是最新的 NodeOS 版本。 在撰写本文时,NodeOS 的 Docker 映像的最后一次更改是在两个月前进行的,而开发版本是在六天前更新的。 因此,如果您想使用最新版本,您绝对应该获取源代码。 这不是太难,但需要很长时间。 你会需要:
- 一台装有 Linux 的计算机。 你可以在 OS X 上编译它,但它需要更长的时间,因为它必须进行交叉编译。 Windows 也是如此。
- Linux 构建实用程序(make、g++、gcc、autoconf)。
- 奇木。
- 时间。 说真的,很多。
一旦你拥有了一切,你可以继续进行源代码编译:
- 下载项目源代码:
bash git clone [email protected]:NodeOS/NodeOS.git
。 - 通过运行以下命令编译它:
cd NodeOS
和npm install
。 - 我将逐字引用官方文档: “挑选一些微波爆米花去看电影。 不,真的,去做吧。” . 是的,这需要很多时间,所以在此期间做一些有趣的事情。
- 运行
bash npm start
在 Qemu 中运行 NodeOS。
它在工作吗?
安装完成后,我们可以通过在 NodeOS shell 中执行命令ls
来检查它是否正常工作。 应该出现这样的输出:
[ 'etc', 'lib', 'lib64', 'root', 'bin', 'sys', 'usr', 'share', 'proc' ]
如果是这样,则意味着一些基本命令正在运行。 但是,如果我们想显示网卡的 IP 地址呢? 在 Linux 下,有一个名为ifconfig
的命令可以做到这一点。 让我们尝试一下:
command not found: ifconfig
似乎缺少ifconfig
命令。 那是因为 NodeOS 没有默认的ifconfig
命令。 怎么办? 嗯,很简单; NodeOS 有一个集成的包管理器(如apt
或yum
),称为npkg
,它基于 Node 的 NPM 并且易于使用。 安装ifconfig
就像运行以下命令一样简单:
npkg install bin-ifconfig
如果一切顺利,命令ifconfig
现在应该在 shell 中可用。 如果我们再次尝试执行它,就会出现这样的输出(出于显而易见的原因,我放了一个随机的 MAC 地址和 IP 地址):
eth0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether 01:23:45:67:89:ab inet6 f0cd::ef01:0203:0405:181%en1 prefixlen 64 scopeid 0x5 inet 192.168.0.21 netmask 0xffffff00 broadcast 192.168.0.21 nd6 options=1<PERFORMNUD> media: autoselect status: active
如果您的输出看起来像那样,那么它正在工作。 您已经成功安装了您的第一个 NodeOS 应用程序: ifconfig
。
这是工作。 但是,我们现在如何处理操作系统?
如果您可以在 Ubuntu 或任何其他 Linux 发行版上做同样的事情(甚至更少的事情),那么拥有一个用 Node.js 编写的操作系统有什么意义呢? 嗯,重点是一切都是通过使用 Node.js 开发的。 这也意味着我们可以只使用 Node.js 来开发我们的应用程序。 例如,NodeOS 没有命令man
的默认实现,该命令在 Linux 上用于显示其他命令的手册页。 不要害怕,实现它很容易。 怎么样,我听到你问了? 简单的。
首先,让我们安装一个名为 Hipster 的文本编辑器,这样我们就可以通过执行以下命令来创建和编辑文件: npm install -g [email protected]
。 这个文件编辑器很简单,绝对不是我会用作其他任何东西的编辑器,但在这种情况下它已经足够好了。 使用 Hipster 创建文件非常简单,只需运行hip filename
,例如hip package.json
; 保存按Ctrl + s
并退出按Ctrl + q
。 对于这个示例,我将使用由主要 NodeOS 开发人员之一开发的代码,我自己并没有真正实现它。 我们示例的原始代码可以在 node-bin-man Git 存储库中找到。

让我们回到创建我们的第一个 NodeOS 应用程序。 与每个 Node.js 应用程序(或 NPM 包)一样,我们首先创建一个package.json
文件,如下例所示:
{ "name": "bin-man", "version": "0.0.1", "description": "Format and display manual pages", "bin": { "man": "man.js" }, "repository": "https://github.com/groundwater/node-bin-man", "author": "groundwater", "license": "MIT", "dependencies": { "blessed": "~0.0.22" } }
参数name
、 version
、 author
、 repository
、 license
和description
是不言自明的。 bin
集合是一个 JSON 键/值对象,其中包含命令名称和关联的 JavaScript 文件。 在我们的示例中, man
命令与文件man.js
相关联。 集合dependencies
包含使用此应用程序所需的 NPM 包列表。 在我们的示例中,代码的作者包括 Blessed,这是一个类似于 curses 的库,具有用于 Node.js 的高级终端接口 API。
现在让我们进入主要部分,实际代码。
#!/usr/bin/env node
这部分称为“shebang”。 NodeOS 实际上并不需要它,但它告诉操作系统如何执行以下代码。 在我们的例子中,它告诉解释器一切都需要使用命令/usr/bin/env node
来执行。
var fs = require('fs'); var blessed = require('blessed');
就像在 Node.js 中一样,函数require()
将选定的包加载到内存中并将其保存到指定的变量中。
var arg = process.argv[2] || 'bin-man';
如果没有指定其他命令, man
命令的标准行为是告诉手册它自己。 我们的代码示例也是这样做的:如果没有为第二个参数指定参数(第一个是 man 本身),则默认为 bin-man。
var path = process.env.HOME + "/lib/node_modules/" + arg + "/README.md"; try{ var readme = fs.readFileSync(path, 'utf-8'); }catch(e){ console.log('No README.md for Package ',arg); process.exit(-1); }
此时,程序会检查给定应用程序是否存在自述文件。 在 NodeOS 中,每个应用程序的安装路径是主目录(或/
),后跟目录lib/node_modules
。 如果文件README.md
存在,它将其内容保存在变量readme
中。 否则,它会显示错误并退出该过程。
// Create a screen object. var screen = blessed.screen(); var box = blessed.box({ content: readme, alwaysScroll:true, scrollable: true, }); // Append our box to the screen. screen.append(box);
Blessed 有一个非常简单的 API; 显示文件的内容就像告诉它创建一个box
并加载内容一样简单。
screen.key(['escape', 'q', 'C-c'], function(ch, key) { return process.exit(0); });
现在,让我们创建一种退出man
应用程序的方法。 我们组合键escape
、 q
或 emacs 风格的组合Cc
来退出进程。
screen.key(['space','f','j','n'], function(ch, key) { box.scroll(box.height); screen.render(); }); screen.key(['down'], function(ch, key) { box.scroll(1); screen.render(); }); screen.key(['up'], function(ch, key) { box.scroll(-1); screen.render(); }); screen.key(['b','k','p'], function(ch, key) { box.scroll(-box.height); screen.render(); });
我们使用方向键向上或向下滚动一行,使用space
、 f
、 j
或n
键向下滚动一页(与屏幕上的行数一样多)。 使用b
, k
或p
做相反的事情。
box.focus(); screen.render();
最后,我们告诉应用程序专注于我们创建的box
并渲染整个东西。 让我们将这些文件放在目录/lib/node_modules/bin-man
,然后添加一个简单的README.md
,如下所示:
# Man Author: @groundwater ## Install npkg install bin-man ## Usage ``` Usage: man PKGNAME Display a packages README.md file ```
我们几乎完成了我们的第一个 NodeOS 自定义应用程序。 只剩下最后一小步了; 我们需要创建一个配置文件,因为它是 NodeOS 应用程序的要求。 就像在路径/etc/bin-man/config.json
中创建一个包含以下内容的文件一样简单: {}
,一个空的 JSON 对象。 现在,我们可以尝试我们的新应用程序。 在 NodeOS shell 中运行man
应该会显示我们之前创建的自述文件。
结论
正如您在我们的简单代码示例中所看到的,在 NodeOS 中实现任何东西都是一件容易的事,您只需要了解 Node.js。
NodeOS 有很大的潜力,我认为一旦实现了附加功能,它可能会成为一个很棒的操作系统。 它仍然需要改进,但由于整个基于 Node.js 的生态系统的流行,如果它迅速成为流行的操作系统,我不会感到惊讶。 你怎么看待这件事? 在评论中告诉我。