月度存档: 十二月 2011

高性价比 NAS+HTPC 折腾记

最近组装了一台 NAS+HTPC 合体的机器,自认为还有比较好的性价比,在折腾了两个星期之后,终于差不多搞定所有功能。这台 HTPC 使用 XBMC 作为媒体中心,使用 OpenMediaVault 作为 NAS 系统,这篇博客主要记录 OpenMediaVault 和 XBMC 的安装过程和问题。另外,因为折腾的时候有些地方来来回回搞了好多次,记录的顺序可能并不严谨。

通过 XBMC 可以直接索引所有电影,使用 themoviedb.org 来获取电影海报、介绍、演员等信息,使用 IMDb 来获取电影的评分。使用 OpenMediaVault 来管理存储,设置共享文件夹等。

在设置成功 VA-API 后,XBMC 就可以使用显卡的硬件加速了,在播放 1080P 时,CPU 占用基本在 20% 左右,还算比较不错了。

当然,在一开始我也可以选择使用 Windows 系统,XBMC 也有 Windows 版本,在 Windows 上基本也不用操心驱动程序的事情,而且 Windows 上设置 Samba 共享也是很方便的。

注意:本篇文章都是以 AMD E350 APU 来讲安装过程的,如果你用的主板并不是 E350,或者型号与我使用的不完全一致,可能安装过程会有不同。另外,因为 OpenMediaVault 是基于 Linux 的,所以这需要你懂一些 Linux 知识。

PS. 另外,本篇文章的操作都是直接使用 root 账户进行,如果你在安装的时候使用了非 root 账户,那么多数操作可能需要加 sudo 来运行。

硬件

  • 机箱:万由 N400 4盘位 NAS 机箱
  • 主板:梅捷 SY-E350-U3M
  • 内存:芝奇 G.Skill DDR3 1333 4G
  • 电源:肯亿 200W 小 1U 电源
  • 系统磁盘:SSK SFD201 USB3.0 16G U盘

因为都是在促销,或者优惠的时候购买的,不包邮费总价在 1400 元左右。

软件

  • 基础系统:Debian Squeeze
  • NAS 系统:OpenMediaVault
  • 媒体中心:XBMC 10.1 Dharma

安装系统

创建 OpenMediaVault 安装盘

因为是用的 NAS 机箱,上面是没有光驱位的,而且我也没有现成的光驱可以用,因为需要用 U 盘来引导安装系统。

首先需要准备一个 512M 以上的 U 盘,然后从 openmediavault.org 下载最新版本的 OpenMediaVault,再使用下面的命令将镜像恢复到 U 盘上:

sudo dd if=openmediavault_0.2.5_i386.iso of=/dev/disk1 bs=4096

注意:disk1 是在我的机器上 U 盘所在的位置,另外,在 dd 恢复镜像的时候,要使用 /dev/disk1,而不是 disk1s1,disk1s1 就会将镜像恢复到某个分区而不是整个 U 盘了。

启动盘注意事项

因为是用的 USB 3.0 的 U 盘,我在安装系统的时候,把 U 盘插在了 USB 3.0 的接口上,但是在系统安装程序启动之后,USB 3.0 的 U 盘没有自动识别出来,因此要将 USB 3.0 的 U 盘插在 USB 2.0 的口上。

在安装的过程中,可以将 Debian 源的地址修改为网易的源镜像,这样安装软件的速度更快一些,网易源的地址为:

http://mirrors.163.com/debian/

安装基本软件

先安装一些基本的软件,包括 X.org,Gnome,GDM3,Vim 和 less:

apt-get install xorg gnome-core gdm3 vim less

Gnome 和 GDM3 其实到后面都不会用到,但是在运行一些需要图形界面的工具时,例如 glxinfo、fglrxinfo,就需要有 X 支持了。

设置 debian-multimedia 源

为了让一些包默认使用 debian-multimedia 的源,先将 debian-multimedia 的源添加到 /etc/apt/sources.list

deb http://www.debian-multimedia.org squeeze main non-free 

并将所有其他源行首添加 # 注释掉,运行 apt-get update 更新源。

在更新完成之后,再将其他源行首的 # 删掉,再次运行 apt-get update 更新源。

安装 debian-multimedia keyring

apt-get install debian-multimedia-keyring

设置 XBMC 用户

添加一个用户 xbmc 用户来运行 XBMC:

useradd -m -s /bin/bash xbmc
passwd xbmc

设置用户 openmediavault 密码

在后面的设置过程中,可能需要管理员权限,而这个时候是用的 openmediavault 这个用户,我不清楚这个用户的默认密码是什么,所以需要先设置这个用户的密码:

passwd openmediavault

启用 SSH

在安装完 OpenMediaVault 之后,就可以直接访问它的 Web 界面了,建议启用 SSH 以便直接在本机进行操作,省去使用键盘看着电视操作的麻烦。

OpenMediaVault 默认的管理员用户名为 admin,密码为 openmediavault

继续阅读 »

推开窗户看世界 — Objective-C之外

引子

App Store 如今正风靡世界,许多人都想尝试去自己开发一个 iOS App,不过苹果官方推荐使用的是 Objective-C 这个语言。而 Objective-C 与 C、Java 之类的语言风格差异有些大,短时间并不容易掌握,又或者许多人只是想尝试开发一个可以运行在 iOS 上的程序而已,不想再去额外去学一门新的语言,那这个时候就可以考虑另外的一些技术来开发 iOS App。

在移动开发领域,得益于现在手机的性能越来越好,浏览器的功能越来越强大,JavaScript 也成为一门很流行的程序开发语言,而对应到 iOS 平台上,也有多种使用 JavaScript 来开发 iOS App 的技术。这次要介绍的三种技术之中,就有两种使用了 JavaScript。

另外,许多开发跨平台移动应用开发的解决方案,首选要支持的就是 iOS,因此在 iOS 这个平台上可以看到很多种不使用 Objective-C 去开发 iOS App 的技术,而且其中技术所编写出来的程序,除了可以在 iOS 上运行之外,还可以运行在 Android 以及其他系统平台上。能少写一份代码,何乐而不为呢~

不使用 Objective-C

这次要介绍的是三个不使用 Objective-C 来开发 iOS App 的解决方案:

这三个解决方案各有特点,它们的运行机制也有所不同,至于在开发 iOS App 时选用何种方案,可以根据每种方案不同的特点去选择适合自己的。

Titanium Mobile

Titanium Mobile 是 AppCelerator 推出的一个基于 JavaScript 的跨平台移动应用开发技术。通过 Titanium Mobile,可以直接使用 JavaScript 开发能运行于 iOS 和 Android 平台的应用程序,而代码只需要写一次。

Titanium Mobile 是通过将 JavaScript 代码映射到对应平台的 Native Code,在 Titanium Mobile 中操作某一个 UI 对象,或者是其他对象时,实时上是在操作对应平台中实际的 UI 对象,例如使用 Ti.UI.createView() 创建一个视图,它在 iOS 中运行时会实际对应到 UIView,使用 Ti.UI.createTabGroup() 就会对应到 iOS 中的 UITabBarController。这样做的好处就是,可以直接使用 JavaScript 来创建出原生的 UI,而不需要使用额外的代码来让程序 UI 更像系统的 UI。

另外,AppCelerator 在收购了 Apatna 之后,推出了适用于 Titanium 的 IDE Titanium Studio,通过使用 Titanium Studio,可以很方便的创建项目、带智能提示的编辑器,以及很方便的调试项目。

在 Titanium Studio 中调试 iOS 项目时,可以做到单步调试,也就意味着,可以拥有不弱于使用 Xcode 开发项目的体验。断点、单步、变量查看功能一应具全。如果需要发布到 App Store,也可以很方便的通过图形化界面来打包。

当然,使用 Titanium Studio 也需要配合 Xcode 来使用,必须要在安装了 Xcode 的情况下,才可以使用 Titanium Studio 来调试和测试项目。

在 Titanium Studio 推出之前,Titanium Mobile 是靠一个 Developer Tool 来进行打包等操作的,相对比较繁琐,而有了 Titanium Studio 之后,让一切变得简单,我也是从那时开始关注 Titanium Mobile。

对于前端开发工程师来说,只需要理解了 iOS 开发中的一些概念,就可以使用 Titanium Mobile 来开发一个像模像样的 iOS App。并且 Titanium Mobile 实现了 CommonJS 规范,可以很方便来模块化程序代码。

PhoneGap

PhoneGap 是一个使用 HTML+CSS+JavaScript 来开发移动 App 的解决方案,使用它来开发 App 只需要有 Web 开发基础即可。它在今年10月份被 Adobe 收购了,然后加入到 Apache Software Foundation 进行孵化。

目前 PhoneGap 已经支持了市面上大多数的智能手机平台,其中就有 iOS。

在我看来,PhoneGap 其实只是提供了一个运行于各种智能手机平台的浏览器的壳,通过这个壳,PhoneGap 的 JavaScript 库可以和系统进行沟通,从而实现在 Web 页面中与系统交互的功能。

因为 PhoneGap 只提供了系统功能的 API 调用,而没有提供任何和界面相关的 API,那么界面就只能自己来折腾了。

幸好开源的世界是强大的,已经有了一堆这样的界面库来供我们选择,像 jQTouchjQuery MobileSencha Touch 之类,都提供了类似于 iOS 的界面组件,可以让我们省去许多界面上的编码工作。

使用浏览器来运行 App 的一个坏处就是:慢。因为整个 App 就是一个网页,如果编码不当,整个程序使用起来体验会比较差,和原生的应用会有很大区别。

在上面提到的几个 UI 框架之中,我比较喜欢的是 jQTouch,它只提供了基本 UI 框架和一些视图切换效果,做出来的程序是一个单页面 App,在整个程序的反应速度上会感觉比较好。不过 jQTouch 也缺少一些常用的组件像对话框,而这些在 jQuery Mobile 和 Sencha Touch 之中又有提供。选择使用哪个框架就要看个人喜好了,它们的网站都提供了在线预览功能

其实,如果用不到系统的 API,只是想把自己的程序包装成一个很像 App 的 App 的话,只要用一用 PhoneGap 提供的壳就行了,它的 API 几乎可以不用看,配合一些 UI 框架可以快速的产出一个 iOS App 来。

当然了,PhoneGap 最大的好处就是,几乎跨了几乎所有的主流智能手机平台,这对于初创团队来说,是迅速推出各个平台客户端的一个好方法。另外 PhoneGap 官方网站也提供了一系列配套服务,例如使用 PhoneGap Build 可以直接编译各个平台的程序安装包,而不需要开发者自己在本地配置每个平台的编译环境。

Mono Touch

Mono Touch 是一个使用 C# 来编写跨平台应用的框架,同样支持了 iOS 和 Android 两大平台。

Mono Touch 对于 .NET 程序员来说应该是一个好消息,除了调试,其他的都可以在 Windows 中搞定,调试的时候可以通过在虚拟机里运行 Mac OS X 来解决。Mono Touch 因为是基于 Mono 的,也有个配套的 IDE 可以用:Mono Develop。因为都是 .NET,当然也可以用 Vistual Studio 这个更强大的工具了。

与 Titanium Mobile 和 PhoneGap 不同的是,Mono Touch 如果要编译到设备,或者发布到 App Store 的话,是需要收费的。

另外,因为 Mono Touch 也是编译成可执行代码再部署到设备上的,因此运行速度相对于 PhoneGap 所制作的应用来说,应该会快上一些。

不过 Mono Touch 要收费,并且收费还不是很便宜,可能会影响到它的普及率。

小结

在上面讲的三个解决方案之外,还有其他好多大大小小的移动应用开发解决方案,但是用于 iOS 上的解决方案,主要也就是映射代码、或者是包装的形式了,对于应用而不是游戏类型来说,一般都是够用的,在具体选择的时候,也可以根据自己更为熟悉哪种语言,或者框架来挑选。

如果你发现了其他有意思的移动应用开发技术,也可以和我分享一下 :)

参考资料

  1. http://www.appcelerator.com/products/titanium-mobile-application-development
  2. http://developer.appcelerator.com/apidoc/mobile/latest
  3. http://phonegap.com/about
  4. https://build.phonegap.com
  5. http://www.mono-project.com/Main_Page
  6. http://xamarin.com/monotouch
  7. https://github.com/xamarin/monotouch-samples
  8. http://blog.zhaojie.me/2010/09/develop-ios-app-with-monotouch-in-visual-studio-1.html

— EOF —

使用 node.js + nginx 建设网站

昨天搞定了一个小网站的搭建,用了 node.js,另外为了能在一个 VPS 上搭建多个网站,用了 nginx 作为反向代理。

软件介绍

嗯,从维基上复制了一下~

node.js

Node.js是一个事件驱动I/O伺服端JavaScript环境,基于V8。目的是为了提供撰写可扩充网络程式,如web服务。第一个版本由Ryan Dahl于2009年释出,后来,Joyent雇用了Dahl,并协助发展Node.js。

nginx

nginx(发音同engine x)是一款由俄罗斯程序员Igor Sysoev所开发轻量级的网页服务器、反向代理服务器以及电子邮件(IMAP/POP3)代理服务器。

cluster

在 node.js 0.6.0 之前,有一个第三方的 node.js 模块 cluster,用来进行多核服务器上运行 node.js,以及提供扩展的支持。但是在 node.js 0.6.0 之后,node.js 本身就提供了 cluster 的支持,另外,第三方的 cluster 也与 node.js 0.6 有兼容性问题。目前 node.js 的稳定版本是 0.6.5,因此需要使用原生的 cluster 来代替第三方的 cluster。

幸好内置的 cluster 也足够简单,如果只是为了多核负载均衡,以及支持即时服务重启的话,只需要写一点的代码就可以完成这些功能了。

server.js

var path = require('path');
var http = require('http');
var cluster = require('cluster');

var NODE_ENV = process.env.NODE_ENV || 'production';
var appName = path.basename(__dirname);
var appPort = 9000;

var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    process.title = appName + ' master';
    console.log(process.title, 'started');

    // 根据 CPU 个数来启动相应数量的 worker
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    process.on('SIGHUP', function() {
        // master 进程忽略 SIGHUP 信号
    });

    cluster.on('death', function(worker) {
        console.log(appName, 'worker', '#' + worker.pid, 'died');
        cluster.fork();
    });

} else {
    process.title = appName + ' worker ' + process.env.NODE_WORKER_ID;
    console.log(process.title, '#' + process.pid, 'started');

    process.on('SIGHUP', function() {
        // 接收到 SIGHUP 信号时,关闭 worker
        process.exit(0);
    });

    http.Server(function(req, res) {
        res.writeHead(200);
        res.end('Worker ' + process.env.NODE_WORKER_ID);
    }).listen(8000);
}

运行服务 node server.js

nodejs master started
nodejs worker 1 #38928 started
nodejs worker 3 #38930 started
nodejs worker 2 #38929 started
nodejs worker 4 #38931 started

如果直接 kill 掉某一个 worker,kill 38928

nodejs worker #38931 died
nodejs worker 5 #38934 started

可以看到一个新的 worker 会马上启动,这就保证了服务的不间断性。

Virtual Host 支持

通常情况下,我们不会在一个 IP 上只部署一个网站。在使用 node.js 时,可以使用 connect 提供的 vhost 支持 Virtual Host,但是,这也限制了服务器只能用 node.js,而不能同时使用其他的服务,例如再安装一个 PHP 服务之类。

这时就可以使用 nginx 的反向代理来解决了,用户在访问网站时,请求先到 nginx 进行处理,如果是 node.js 站点的话,将请求转发到 node.js 的服务,然后再将 node.js 服务的结果返回给用户。

在 nginx 中设置反向代理很简单,一句 proxy_pass 就可以搞定:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:9000;
    }
}

在添加了 Virtual Host 之后,就可以把一些静态资源,例如 CSS、JavaScript 之类的文件,直接交给 nginx 来处理,而不是什么请求都需要到 node.js 这一层去处理,也省去反向代理这一关的消耗。

Session 支持

使用 express 这个 node.js web framework 来创建网站时,可以配合 connect 这个中间件来实现 session 支持。

默认情况下,connect 的 session 是使用内置的内存存储来存放 session 信息,这时如果 node.js 服务一旦重启,所有的 session 信息都会丢失,这对于用户来说不是个好体验,那么我们可以用外部的存储来存放 session 信息,例如 redis。

要让 connect 使用 redis 作为 session 存储的话也是很方便的:

var express = require('express');
var RedisStore = require('connect-redis')(express);

var app = express.createServer(
    express.session({ secret: 'keyboard cat', store : new RedisStore() })
);

监测文件改动

在调试的时候,经常需要重新启动 node.js 以便修改过的文件生效,原来第三方的 cluster 有一个配置项,可以很方便的配置监测时间间隔,文件改动后自动重新启动 worker,但是原生的 cluster 就没有这个功能了,需要自己来实现。

fs 模块提供了 watch 函数,可以方便的监测文件修改,使用这个就可以来实现文件修改后自动重启 woker 功能了。

if (cluster.isMaster) {
    process.title = appName + ' master';
    console.log(process.title, 'started');

    var workers = [];

    // 根据 CPU 个数来启动相应数量的 worker
    for (var i = 0; i < numCPUs; i++) {
        var worker = cluster.fork();
        workers.push(worker.pid);
    }

    process.on('SIGHUP', function() {
        // master 进程忽略 SIGHUP 信号
    });

    // 监测文件改动,如果有修改,就将所有的 worker kill 掉
    fs.watch(__dirname, function(event, filename) {
        workers.forEach(function(pid) {
            process.kill(pid);
        });
    });

    cluster.on('death', function(worker) {
        var index = workers.indexOf(worker.pid);
        if (index != -1) {
            workers.splice(index, 1);
        }
        console.log(appName, 'worker', '#' + worker.pid, 'died');
        worker = cluster.fork();
        workers.push(worker.pid);
    });

}

这样,每次文件保存之后,node.js 都会自动重启,从而避免了每次保存文件要手动重启服务的麻烦。

当然,在使用监测文件自动重启的时候,最好加上 NODE_ENV 的判断,在 development 的时候才进行自动重启,而 production 的时候使用手动重启就够了。

小结

总的来说,使用 node.js 来构建网站还是很方便的,加上 nginx 反向代理之后,与使用 PHP 之前也没有很大的区别,又可以享受到 node.js 的高效。

嗯,就这样了,希望此文对你有所帮助。

参考资料

  1. https://zh.wikipedia.org/wiki/Node.js
  2. http://nodejs.org/docs/v0.6.5/api/cluster.html
  3. http://learnboost.github.com/cluster/
  4. http://expressjs.com/
  5. http://senchalabs.github.com/connect/
  6. http://redis.io/

— EOF —