posts - 43,  comments - 394,  trackbacks - 18
公告

    一直以来都十分关注mono的发展,在不久之前,mono正式发布了2.6.1版本,该版本已经是一个比较完善的版本了,不仅完整支持了.net2.0的全部内容,大部分.net3.5甚至还支持了.net4.0的内容(可选),在mono官方已经包含了asp.net mvc1.0版本,因此,部署levenblog到mono的条件完全成熟,不过由于linux和windows的差异,因此,也并不是所有程序都可以直接部署的,本次将完整记录levenblog部署到mono2.6.1的过程.

    首先给出服务器平台,我测试了两个平台,debian5 x86和debian5 x64,都通过源码编译的方式安装了mono2.6.1,不过在安装的时候,debian5 x64编译mono出现莫名的错误(编译器未给出任何有效错误信息而错误),因此,改为checkout最新的源码安装成功).这样应该能广泛代表linux32位和64位平台了.就针对levenblog程序来说,以前的版本在mono是无法直接运行的.经过初步的分析,存在以下一些问题:

  1. 本地路径问题,这可能是大部分.net程序部署到linux+mono的一个最大问题,往往大家在windows上写程序并不注意路径,linux中使用"/"作为路径分隔符,但是windows确是"\",同时,如果程序中对路径进行操作,手动拼接基本上都会出现问题,该问题的解决方法:抛弃手动拼接本地路径的做法,改用Path.Combine方法来进行和平台无关的路径操作,levenblog中存在该问题的地方主要是skin选择程序和上传程序.
  2. 仍然是路径问题,不过这次是虚拟路径问题,主要问题在于使用master page的文件,levenblog的view中大量使用master page,默认的引用方式为"../shared/blog.master",然而,这种模式在mono中将无法解析,提示路径错误,原因好像是它并不是使用master page的实际路径来分析相对路径,而是采用url路径进行解析,而mvc应用中,url和物理路径并不相同,于是导致路径报错,这应该也算是一个mono和.net不相容的问题,解决的方式是引用master page的时候一律采用~/xxx的方式,比如~/skins/default/shared/blog.master,不过这种方式会规定死了相对路径,因此,skin的目录将不能被改名,否则系统也无法找到该文件.
  3. 仍然是路径,果然mono移植最大的问题还是路径,这次出现问题的web.config中的外部引用,因为配置文件过大,levenblog将log,route,高亮等配置文件分离,并在web.config中包含,在windows中我们只能采用<routeConfigure configSource="config\route.config" />这样的模式,然而,在linux+mono中,这样的路径被认为是"config\route.config"文件,这是因为\在linux中是合法文件字符,因此,在linux+mono中,该处应该改为<routeConfgure configSource="./config/route.config" />不过这样的配置方式可别指望在windows下工作,windows下的exception明确表示,配置文件路径包含必须是相对路径且不能包含字符'/',因此,针对两个不同的环境levenblog得准备不同的web.config文件.
  4. 关于native dll-sqlite3.dll的处理,很显然,sqlite3.dll是windows上的dll文件,是无法在linux上运行的,而System.Data.SQLite.dll是会通过DllImport导入sqlite3.dll中的函数,同时,mono上的链接库文件也绝不会取名为*.dll的模式,因此,mono采用了一种dllmap的配置方式来在内部进行转向,于是,sqlite3.dll被映射至libsqlite3.so.0,不过很遗憾,debian5中通过apt-get安装的libsqlite3.so.0是无法支持新版的System.Data.SQLite.dll的,会提示调用错误,因此,我们需要自己找最新的libsqlite3.so.0,对于32位系统,在sqlite的官方网站就提供了下载,具体地址为:http://www.sqlite.org/sqlite-3.6.22.so.gz (针对3.6.22),而64位版本需要自行进行编译,由于本程序无需tcl支持,所以可以只下载基本的sqlite版本即可,地址为:http://www.sqlite.org/sqlite-amalgamation-3.6.22.tar.gz,编译之后,在.libs目录下可以看到"libsqlite3.so.0"文件,为了不影响系统依赖,建议不要将该文件覆盖到/usr/lib,如果方便,可以放入/usr/local/lib或者bin目录.然而,这样操作了系统仍然无法找到正确的libsqlite3.so.0,这是因为linux上,无论是/usr/local/lib还是当前bin都不是lib的的搜索路径,为了让mono执行前能搜索到这些路径,需要手动执行"export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH"将/usr/local/lib加入lib(注意,linux中环境变量用:间隔,如果将libsqlite3.so.0放入当前bin目录,那么需要将该目录也加入到LD_LIBRARY_PATH路径).经过这样一番折腾,系统终于找到了正确的libsqlite3.so.0文件,首页总算完全打开.
  5. 验证码问题,通过源码安装的mono,很可能出现验证码无法显示的情况,出现这样的情况,首先要检查是否安装了libgdiplus组件,如果没有,请务必安装该组件,它是系统System.Drawing组件工作的基础,其2.6.1版本的下载地址为:http://ftp.novell.com/pub/mono/sources/libgdiplus/libgdiplus-2.6.tar.bz2,同时注意安装前请保证系统已经安装了基本的libjpeg,libgpng,libgif库,否则安装后也会出现这些格式的验证码无法显示的情况,安装成功后,还需要注意一定要将安装路径中的lib加入到系统lib搜索路径,比如我将该组件安装到/usr/local/lib,那么已经要将该路径export到LD_LIBRARY_PATH中,否则系统找不到对应的库,也会无法显示.
  6. 文件编码问题,经过上面几部基本页面都能正常使用了,但是仍然有部分页面出现了乱码,经过检查这些页面使用了gbk编码,将其改为utf-8,乱码问题解决
  7. 文件名大小写问题,这也是一个部署经常出现的问题,在最开始的时候曾经出现一个"System.Data.SQLite.dll"无法找到的问题,通过错误排查,最后发现是bin中文件名为Syste.Data.SQLite.DLL,大小写的差别导致mono无法加载该文件而错误,同样的,在页面中,引用任何静态文件,路径都必须保证大小写一致,在levenblog中,这样的不规则出现在css引用图片中,经过修改,全部改成小写,故障排除
  8. mono编译器和微软编译器有个别不相容情况,对于levenblog,表现在日历组件中,其中一行代码如下
    startDate = startDate.AddDays(0 - startDate.DayOfWeek);
    mono下会提示DayOfWeek无法转换为int,而微软编译器可以支持该转换,改为
    startDate = startDate.AddDays(0 - (int)startDate.DayOfWeek);
    故障解决
  9. 个别API不支持,在admin/info.aspx中,调用了Cache.EffectivePrivateBytesLimit获取服务器可分配内存,但是该调用在mono中是不被支持的,仍然去掉,还好这样的不相容还是极个别的.
  10. js中嵌入c#代码会解析错乱,这是目前发现mono最大的一个bug,在write.aspx中,部分js需要在其中嵌入c#代码,结果运行之后导致输出错乱而js执行错误的情况,该问题目前没有直接解决方法,通过变通,我新增了一个名为js的action用来处理js输出,

    通过解决以上10个问题之后,levenblog终于成功在linux+mono的环境下运行起来,总的来说,移植并没有出现很大的问题,

    我通过nginx+fastcgi-mono-server2的模式测试配置了一个levenblog运行环境,配置方法参考以上10点,测试地址为:http://leven.name/,欢迎有兴趣的朋友进行测试.同时,在下一个levenblog版本发布时,我会提供完整稳定的linux+mono安装包.

posted on 2010-01-14 00:03 Leven 阅读(...) 评论(...) 编辑 收藏
CopyRight 2008, Leven's Blog xhtml | css
Leven的个人Blog