天天看點

基于 JavaScript 的作業系統你聽說過嗎?基于 JavaScript 的作業系統你聽說過嗎?

我想大多數人聽說過 node.js,但是你聽說過 nodeos 嗎?沒錯,nodeos,一個用 node.js 寫的作業系統。好吧,實話說,nodeos 用 linux 核心來處理各種底層任務,比如硬體通訊什麼的,但是除此之外,使用的都是 node.js。nodeos 的開發始于兩年前,建立者的目的很簡單,他隻是好奇,“是否有可能僅使用 node.js 建立一個作業系統呢?” 

基于 JavaScript 的作業系統你聽說過嗎?基于 JavaScript 的作業系統你聽說過嗎?

是否有可能僅使用 node.js 建立一個作業系統呢?

<a></a>

我們已經看到了 node.js 在這幾年已經取得如此迅猛的發展,那麼我們為何不讓它更酷一些呢?比如用它做個作業系統。

nodeos 引入了一個有趣的特性:所有的使用者都有一個獨立的檔案系統,他們在一個簡單的檔案系統中完成各種工作。因為他們的“主目錄”事實上就是他們自己的檔案系統的根(root),是以他們可以不需要任何超級權限就可以将軟體包安裝到系統中,也不需要配置什麼,因為軟體包預設就安裝在他們自己的主目錄裡面。此外,這樣也提供了良好的安全性,如果黑客攻入到了某個賬戶,那麼隻能通路到該使用者所在的部分,最終的結果就是黑客并不能由此影響到整個系統。

你可以想想,如果一個作業系統使用 node.js,那就意味着所有在 npm 中可用的包同時也都是 nodeos 的軟體包。在寫作本文時,已經有了超過 21 萬的軟體包,而且每分每秒都在不斷增長。如果幾年以後,nodeos 有了一百萬應用,那也沒什麼好奇怪的。

這看起來并不算什麼,linux 是大多數伺服器所采用的作業系統。因為 nodeos 是基于 linux 核心的,是以你隻需要很少的修改就可以使用那些給其它的 linux 發行版開發的應用了。

我非常希望 nodeos 是一個已經完成的作品,但是,它現在還不是。它仍然缺少一些伺服器作業系統所必需的關鍵功能。比如,缺失完整的 bash 工具集,包括 ps、tail、nano 和 grep 等都沒有。更糟糕的是,你也不能把它當成桌面作業系統使用,因為它沒有 gui。當然,你可以實作一些缺失的功能,隻需要使用一點點 javascript,但是預設情況下,這些功能現在都還沒有,真糟糕。

最容易、最快捷的體驗 nodeos 的方法如下:

一台運作 mac osx 或 linux 計算機,也許 windows 也可以,但是我沒試過。

docker。

當你安裝好 docker 之後,運作一個 nodeos 執行個體是很容易的。你隻需要執行如下指令就可以了, docker 會為你完成這魔法般的一切:

<code>sudo docker run -t -i nodeos/nodeos</code>

基于 JavaScript 的作業系統你聽說過嗎?基于 JavaScript 的作業系統你聽說過嗎?

最容易、最快捷的體驗 nodeos 的方法是通過 docker。

當你運作了上述指令,docker 會自動從倉庫下載下傳 nodeos 的鏡像,并将其安裝到一個虛拟環境中。安裝好之後,會打開一個連接配接到 nodeos 的 ssh 會話。

有些情況下你也許不能使用 docker 來體驗,或者是你想體驗一下最新版本的 nodeos 。在寫作本文時,nodeos 的鏡像已經是兩個月前生成的了,而開發版本則是六天前更新的。是以,如果你希望使用最新版本,你應該從源代碼開始。這也不算很難,但是要花費一些時間。你需要:

一台運作 linux 的計算機。你可以在 os x 上編譯它,但是跨平台編譯需要花費很多時間,對于 windows 也如此。

linux 編譯建構相關的工具(make、g++、gcc、autoconf)。

qemu。

時間,真的需要很多。

如果萬事俱備,你就可以從源代碼開始編譯了:

下載下傳項目源代碼:<code>bash git clone [email protected]:nodeos/nodeos.git</code>。

使用下列指令編譯: <code>cd nodeos</code> 并 <code>npm install</code>。

我逐字引用了其官方文檔的話:“拿上爆米花去看場電影吧,不開玩笑,真的。”,是的,它需要很多時間,做些有意思的事情去吧。

執行 <code>bash npm start</code> 來在 qemu 中運作 nodeos。

當安裝完成後,我們可以通過在 nodeos 的 shell 中執行  <code>ls</code>指令來看看它是否工作了。輸出類似如下:

<code>[ 'etc', 'lib', 'lib64', 'root', 'bin', 'sys', 'usr', 'share', 'proc' ]</code>

如果顯示如上,說明一些基本的指令可以工作了。但是如果我們想要知道網卡位址呢?在 linux 下,這個指令是  <code>ifconfig</code> ,讓我們試試:

<code>command not found: ifconfig</code>

看起來沒有 <code>ifconfig</code> 指令。這是因為 nodeos 預設沒有  <code>ifconfig</code>指令。現在怎麼辦?很簡單,nodeos 有一個內建的包管理器(類似 <code>apt</code> 或 <code>yum</code>) ,叫做 <code>npkg</code>,它是基于 node 的 npm 的,很容易使用。可以通過如下指令很友善的安裝 <code>ifconfig</code> :

<code>npkg install bin-ifconfig</code>

如果一切正常, <code>ifconfig</code> 指令現在就可以在 shell 中使用了。我們再次試着執行一下,輸出類似如下:(我替換了其中的 mac 位址):

<code>eth0: flags=8863&lt;up,broadcast,smart,running,simplex,multicast&gt; mtu 1500</code>

<code>ether 01:23:45:67:89:ab</code>

<code>inet6 f0cd::ef01:0203:0405:181%en1 prefixlen 64 scopeid 0x5</code>

<code>inet 192.168.0.21 netmask 0xffffff00 broadcast 192.168.0.21</code>

<code>nd6 options=1&lt;performnud&gt;</code>

<code>media: autoselect</code>

<code>status: active</code>

如果你的輸出也類似如上,那說明它可以工作了。你已經成功地安裝了你的第一個 nodeos 應用: <code>ifconfig</code>。

基于 JavaScript 的作業系統你聽說過嗎?基于 JavaScript 的作業系統你聽說過嗎?

使用 node.js 建構一個 nodeos 應用

首先讓我們來安裝一個叫做 hipster 的文本編輯器,以便我們可以建立和編輯檔案。執行如下指令: <code>npm install -g [email protected]</code>。這個文本編輯器很簡單,除了用作文本編輯之外啥也幹不了,不過對于我們來說足夠了。

用 hipster 建立檔案很簡單,運作 <code>hip filename</code>即可,如: <code>hip package.json</code>。要儲存檔案請按下 <code>ctrl + s</code> ,退出按下 <code>ctrl + q</code>。

讓我們回過頭來建立我們的第一個 nodeos 應用。像每個 node.js 應用(或 npm 包)一樣,我們從建立一個 <code>package.json</code> 檔案開始,内容如下:

<code>{</code>

<code>"name": "bin-man",</code>

<code>"version": "0.0.1",</code>

<code>"description": "format and display manual pages",</code>

<code>"bin": {</code>

<code>"man": "man.js"</code>

<code>},</code>

<code>"repository": "https://github.com/groundwater/node-bin-man",</code>

<code>"author": "groundwater",</code>

<code>"license": "mit",</code>

<code>"dependencies": {</code>

<code>"blessed": "~0.0.22"</code>

<code>}</code>

這些參數 <code>name</code>、<code>version</code>、 <code>author</code>、 <code>repository</code>、 <code>license</code>和 <code>description</code> 是其意自明的。這個<code>bin</code> 集合是一個 json 的鍵值對對象,包含了指令名及其關聯的 javascript 檔案。在我們的例子中, <code>man</code> 指令關聯到  <code>man.js</code>檔案。而  <code>dependencies</code>集合包含了這個應用所需要的 npm 包的清單。在我們的例子中,代碼的作者包含了 blessed 包,這是一個類 curses 的庫,可以讓 node.js 支援進階終端界面的 api。

現在我們進入了主要的部分,實際的代碼。

<code>#!/usr/bin/env node</code>

<code>var fs = require('fs');</code>

<code>var blessed = require('blessed');</code>

像在 node.js 中一樣, <code>require()</code> 函數加載標明的包到記憶體中,并将其儲存為特定的變量。

<code>var arg = process.argv[2] || 'bin-man';</code>

 <code>man</code> 指令的标準行為是如果沒有指定要檢視的指令時,就顯示它自己的幫助資訊。在我們的代碼示例中也一樣:如果沒有給出第二個參數(第一個參數是 man 本身),那麼該參數的預設值是 bin-man。

<code>var path = process.env.home + "/lib/node_modules/" + arg + "/readme.md";</code>

<code></code>

<code>try{</code>

<code>var readme = fs.readfilesync(path, 'utf-8');</code>

<code>}catch(e){</code>

<code>console.log('no readme.md for package ',arg);</code>

<code>process.exit(-1);</code>

在這裡,程式檢查給定的應用是否有一個 readme 檔案。在 nodeos 中,每個應用的安裝路徑是其主目錄(/)下的 <code>lib/node_modules</code>。如果 <code>readme.md</code> 檔案存在,就将其内容儲存到 <code>readme</code>變量中。否則,顯示一個錯誤資訊并退出。

<code>// create a screen object.</code>

<code>var screen = blessed.screen();</code>

<code>var box = blessed.box({</code>

<code>content: readme,</code>

<code>alwaysscroll:true,</code>

<code>scrollable: true,</code>

<code>});</code>

<code>// append our box to the screen.</code>

<code>screen.append(box);</code>

blessed 有一個非常簡單的 api,要顯示一個檔案的内容很容易,隻需要建立一個  <code>box</code> ,然後載入内容即可。

<code>screen.key(['escape', 'q', 'c-c'], function(ch, key) {</code>

<code>return process.exit(0);</code>

現在,讓我們找個退出  <code>man</code> 應用的方法。我們組合了  <code>escape</code>、 <code>q</code> 或 emacs 風格的 <code>c-c</code> 來退出應用。

<code>screen.key(['space','f','j','n'], function(ch, key) {</code>

<code>box.scroll(box.height);</code>

<code>screen.render();</code>

<code>screen.key(['down'], function(ch, key) {</code>

<code>box.scroll(1);</code>

<code>screen.key(['up'], function(ch, key) {</code>

<code>box.scroll(-1);</code>

<code>screen.key(['b','k','p'], function(ch, key) {</code>

<code>box.scroll(-box.height);</code>

我們使用方向鍵來上滾和下滾,用 <code>space</code>、 <code>f</code>、 <code>j</code> 或 <code>n</code> 向下翻頁,<code>b</code>、 <code>k</code> 或 <code>p</code> 向上翻頁。

<code>box.focus();</code>

最後,我們讓應用将輸入焦點放到  <code>box</code> ,我們在這裡建立和渲染所有内容。

把上面編輯的這個檔案存放到  <code>/lib/node_modules/bin-man</code> 目錄下(名字是 <code>man.js</code>),并加一個簡單的  <code>readme.md</code> ,類似如下:

<code># man</code>

<code>author: @groundwater</code>

<code>## install</code>

<code>npkg install bin-man</code>

<code>## usage</code>

<code>```</code>

<code>usage: man pkgname</code>

<code>display a packages readme.md file</code>

我們已經基本完成了我們的第一個 nodeos 定制應用。最後剩下一小步了,我們需要建立一個 nodeos 應用需要的配置檔案。很簡單,把它建立到 <code>/etc/bin-man/config.json</code> ,内容隻是一個空的 json 對象: <code>{}</code>。

現在我們可以試試我們的新應用了。在 nodeos 中運作 <code>man</code> ,它将展示我們之前建立的 readme 檔案。

如你所見,在 nodeos 中實作任何東西都很簡單,你隻需要懂得 node.js 即可。

nodeos 很有潛力,我認為當實作了更多的功能之後它會成為一個偉大的作業系統。目前仍然需要很多工作,但是在整個node.js 生态系統興盛發展的形勢下,萬一哪天它很快地成為一個流行的作業系統也沒什麼好驚奇的。

你怎麼看?發表你的評論讓我們知道。 

本文來自雲栖社群合作夥伴“linux中國”

原文釋出時間為:2013-04-02.