Mono+Jexus部署C# MVC的各種坑


  如果你看到這篇文章,先別急着動手,過完一遍,確定是你要的再動手。

  別人提到的這里不贅述,只說查了好久才知道的。

1號坑:System.IO.FileNotFoundException Could not find file "roslyn\csc.exe".
詳細信息如下:

System.IO.FileNotFoundException
Could not find file "/var/www/defalut/bin\roslyn\csc.exe".

Description: HTTP 500.Error processing request.

Details: Non-web exception. Exception origin (name of application or object): mscorlib.
Exception stack trace:
  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) <0x41aaab70 + 0x006e7> in     <filename unknown>:0 
  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share) <0x41bba470 + 0x00053> in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)
  at System.IO.File.OpenRead (System.String path) <0x41bc4b50 + 0x0003f> in <filename unknown>:0 
  at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.get_CompilerName () <0x41e0fb40 + 0x00086> in <filename unknown>:0 
  at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.FromFileBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) <0x41e1d600 + 0x005ce> in     <filename unknown>:0 

只貼其中的一部分,但是大致一看也能看出路徑有問題,問題的原因:

http://www.mono-project.com/docs/advanced/iomap/

Mono官方網站給出的解釋及解決方案如下:

The Problem

Windows developers are used to a case-insensitive file system, which means that they might create a file called “mydata” in one place, and try to access it somewhere else as “MyData” or as “MYDATA”. This breaks on most Unix setups because Unix is case sensitive[1].

Another problem is that developers sometimes hardcode the directory separator character in their source code (“\”) instead of using Path.DirectorySeparator and using Path.Combine for combining this paths. This is a problem because “\” is a valid file name components on Unix. This means that if an application hardcodes for example “Logs\access_log”, in Unix this will not store the contents in the “Logs” directory as the file “access_log”. Instead, it will store the results in a file called “Logs\access_log”.

Only a few applications cope with drive letters, but they might still pose a problem as the colon is a valid filename in Unix, which means that “A:\file” is a valid filename in the current directory.

Although .NET provides the tools to write code that is portable, in practice, they do not use these features (the exception is Path.Combine, which some people use, as it is genuinely useful on its own).

The Usual Solution

When moving applications from Windows to Linux, it is always necessary to run the application, run its test suite, and validate that the application works as intended. With the path problems described above, the process above included a number of iterations to fix the assumptions made by programmers about the file system.

This process could be time consuming, because identifying where the mistakes were made could take some time, the program might fail with FileNotFound exceptions (when referencing files that were not there), data would show up empty (listing contents of a directory that had nothing, as all the data went elsewhere) but it was doable.

This process works as long as you have the source code to all the components that you are porting, but if you were using a third-party library that you had no source code for, you would not be able to fix the problems.

The New Solution

Mono now has a portability layer into Mono that will address those problems without requiring changes to your code. This will remove a large component of the porting cycle as a whole class of obnoxious problems are gone.

The new portability framework is enabled by setting the environment variable MONO_IOMAP (which we will likely rename to something shorter) to one of the following values:

  • case: makes all file system access case insensitive.
  • drive: strips drive name from pathnames.
  • all: enables both case and drive.

In addition, if any of those options are enabled, the directory separator mapping is also turned on. So this basically means that you have to type this, or include this in your script that launches your application:

   $ export MONO_IOMAP=all
   $ mono myapp.exe

For ASP.NET applications hosted with mod_mono, you can add the following directive to your Apache configuration file:

 MonoSetEnv MONO_IOMAP=all

This new feature appeared in Mono 1.1.18 and is available in all new Mono 1.2.x versions as well.

The downside is that Mono will have to do some extra work when coping with your file system, to search for case insensitive file names. So if your application is still a portable application, you will be much better off without this switch.

[1] Some Linux file systems are case insensitive, and some folks have used a combination of hacks, including doing loopback CIFS mounts to get case sensitivity issues out of the way; OS X does not have this particular problem, but it still has the others.

2號坑:System.InvalidOperationException  Process has not been started.

詳細信息如下:

Description: HTTP 500.Error processing request.
Details: Non-web exception. Exception origin (name of application or object): System.
Exception stack trace:
  at System.Diagnostics.Process.get_ExitCode () <0x414b69b0 + 0x000a3> in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_ExitCode ()
  at System.CodeDom.Compiler.Executor.InternalExecWaitWithCapture (System.String cmd, System.String currentDir, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName) <0x414b3ec0 + 0x00403> in <filename unknown>:0 
  at System.CodeDom.Compiler.Executor.ExecWaitWithCapture (IntPtr userToken, System.String cmd, System.String currentDir, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName) <0x414b3c00 + 0x00057> in <filename unknown>:0 
  at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.Compile (System.CodeDom.Compiler.CompilerParameters options, System.String compilerFullPath, System.String arguments, System.String& outputFile, System.Int32& nativeReturnValue) <0x414b37e0 + 0x0010b> in <filename unknown>:0 
  at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.FromFileBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) <0x414b03e0 + 0x005ef> in <filename unknown>:0 
  at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.CompileAssemblyFromFileBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) <0x414b0250 + 0x000c7> in <filename unknown>:0 
  at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) <0x414b00b0 + 0x00049> in <filename unknown>:0 
  at System.Web.Compilation.AssemblyBuilder.BuildAssembly (System.Web.VirtualPath virtualPath, System.CodeDom.Compiler.CompilerParameters options) <0x4149bd40 + 0x00979> in <filename unknown>:0 
  at System.Web.Compilation.AssemblyBuilder.BuildAssembly (System.Web.VirtualPath virtualPath) <0x4149bd00 + 0x00023> in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.GenerateAssembly (System.Web.Compilation.AssemblyBuilder abuilder, System.Web.Compilation.BuildProviderGroup group, System.Web.VirtualPath vp, Boolean debug) <0x414913e0 + 0x0097b> in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.BuildInner (System.Web.VirtualPath vp, Boolean debug) <0x41444aa0 + 0x0050b> in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.Build (System.Web.VirtualPath vp) <0x41444520 + 0x000ff> in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.GetCompiledType (System.Web.VirtualPath virtualPath) <0x41443e20 + 0x0008f> in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.GetCompiledType (System.String virtualPath) <0x41443a50 + 0x00017> in <filename unknown>:0 
  at System.Web.HttpApplicationFactory.InitType (System.Web.HttpContext context) <0x413dd430 + 0x003f3> in <filename unknown>:0 

 我這里只是創建的一個簡單的MVC Demo,接下來需要做的幾件事。其實這樣做完上面的兩個問題都不會遇到。

Microsoft.AspNet.Mvc.5.2.3
修改為
Microsoft.AspNet.Mvc.4.0.30506

Microsoft.AspNet.Razor.3.2.3
修改為
Microsoft.AspNet.Razor.2.0.30506
此時
Microsoft.AspNet.WebPages.3.2.3
會自動替換為
Microsoft.AspNet.WebPages.2.0.30506

卸載
Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0

項目中的Web.config需要作的修改(修改版本信息,要與項目引用的一致。)
System.Web.Razor
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>

System.Web.WebPages.Razor
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>

Views下的Web.config需要作的修改(修改版本信息,要與項目引用的一致。)
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> </sectionGroup> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

點擊Demo下載。

部署復雜的項目依然問題多多,路漫漫···

System.DllNotFoundException
libdl
Description: HTTP 500.Error processing request. Details: Non-web exception. Exception stack trace: at (wrapper managed-to-native) ZeroMQ.lib.Platform+Posix:dlopen (intptr,int) at ZeroMQ.lib.Platform+Posix.OpenHandle (System.String fileName)
<0x41ad8800 + 0x00027> in <filename unknown>:0 at ZeroMQ.lib.Platform+Posix.LoadUnmanagedLibrary (System.String libraryName) <0x41ad8070 + 0x001e7> in <filename unknown>:0 at ZeroMQ.lib.zmq..cctor () <0x41ad6000 + 0x01070> in <filename unknown>:0

宇內大大指點在mono的配置文件/etc/mono/config中添加一行:

<dllmap dll="libdl" target="libdl.so.2" os="!windows"/>

這個問題就過了,接下來的新問題:

System.DllNotFoundException
libzmq.so: cannot open shared object file: No such file or directory

Description: HTTP 500.Error processing request.
Details: Non-web exception.
Exception stack trace:

在容器中先后找到libzmq.so的文件和將要放置的位置

root@0780a91692aa:/# find / -name libzmq.so
/var/www/mvc/bin/amd64/libzmq.so
/var/www/mvc/bin/i386/libzmq.so
root@0780a91692aa:/# find / -name libdl.so.2
/lib/x86_64-linux-gnu/libdl.so.2
root@0780a91692aa:/# cp /var/www/mvc/bin/amd64/libzmq.so /lib/x86_64-linux-gnu/    
root@0780a91692aa:/# ldconfig
root@0780a91692aa:/# find / -name libzmq.so                                                   
/lib/x86_64-linux-gnu/libzmq.so
/var/www/mvc/bin/amd64/libzmq.so
/var/www/mvc/bin/i386/libzmq.so
root@0780a91692aa:/# /usr/jexus/jws restart
Restarting ... OK

發現問題又變了,也就是這關算過了

System.DllNotFoundException
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.15' not found (required by /lib/x86_64-linux-gnu/libzmq.so)

Description: HTTP 500.Error processing request.
Details: Non-web exception.
Exception stack trace:

先查看一下容器中系統的ldd版本

root@0780a91692aa:/# ldd --version
ldd (Debian EGLIBC 2.13-38+deb7u10) 2.13
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

發現比要求的版本要低,嘗試升級系統

root@0780a91692aa:/# apt-get update                                                           
Hit http://download.mono-project.com wheezy/snapshots/4.2.3.4 Release.gpg
Hit http://download.mono-project.com wheezy/snapshots/4.2.3.4 Release                         
Hit http://download.mono-project.com wheezy/snapshots/4.2.3.4/main amd64 Packages             
Hit http://httpredir.debian.org wheezy Release.gpg                          
Hit http://httpredir.debian.org wheezy-updates Release.gpg                    
Hit http://httpredir.debian.org wheezy Release                                
Hit http://security.debian.org wheezy/updates Release.gpg             
Hit http://httpredir.debian.org wheezy-updates Release
Hit http://security.debian.org wheezy/updates Release                 
Hit http://security.debian.org wheezy/updates/main amd64 Packages     
Hit http://httpredir.debian.org wheezy/main amd64 Packages
Hit http://httpredir.debian.org wheezy-updates/main amd64 Packages
Reading package lists... Done            
W: Conflicting distribution: http://download.mono-project.com wheezy/snapshots/4.2.3.4 Release (expected wheezy/snapshots but got wheezy)
root@0780a91692aa:/# apt-get upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
root@0780a91692aa:/# apt-get dist-upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
root@0780a91692aa:/# ldd --version
ldd (Debian EGLIBC 2.13-38+deb7u10) 2.13
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

發現ldd的版本並沒有發生改變,叼了···宇內大大的意思是在debian7中重新編譯 zeroQM。我不知道怎么搞,直接重新構建個新鏡像得了。Dockerfile內容如下:

FROM ubuntu:14.04

MAINTAINER Mongo <willem@xcloudbiz.com>

RUN apt-get update \
        && apt-get install -y curl \
        && rm -rf /var/lib/apt/lists/*

RUN sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF

RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | sudo tee -a /etc/apt/source$
        && sudo apt-get update \
        && apt-get install -y mono-devel \
        && rm -rf /var/lib/apt/lists/*

RUN cd /opt
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get -y install wget
RUN wget linuxdot.net/down/jexus-5.8.1.tar.gz
RUN tar -zxvf jexus-5.8.1.tar.gz
RUN ./jexus-5.8.1/install
RUN rm jexus-5.8.1.tar.gz

ENV SITE_CONF /usr/jexus/siteconf

COPY default $SITE_CONF/default

EXPOSE 80

RUN apt-get -y install vim
#CMD /usr/jexus/jws start && tail -f

結果

···
Processing triggers for libc-bin (2.19-0ubuntu6.7) ...
 ---> 95aa70915ed3
Removing intermediate container 4dcdd097c9df
Successfully built 95aa70915ed3

跑起來又是坑

System.MissingMethodException
Method not found: 'System.Web.HttpApplication.RegisterModule'.

Description: HTTP 500.Error processing request.
Details: Non-web exception. Exception origin (name of application or object): mscorlib.
Exception stack trace:
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0 

經過查找資料才發現這是Mono早期版本的BUG,而查看了一下通過Dockerfile安裝的mono版本才發現是3.2.8,看來需要修改下Dockerfile了。

FROM ubuntu:14.04

MAINTAINER Mongo <willem@xcloudbiz.com>

RUN apt-get update
RUN apt-get -y upgrade
RUN sudo apt-get -y install build-essential automake autoconf bison gettext libtool libgli$
RUN sudo apt-get -y install libgif-dev libtiff4-dev libpng12-dev libexif-dev libx11-dev li$

RUN cd /opt
RUN apt-get -y install wget
RUN wget http://download.mono-project.com/sources/mono/mono-4.4.0.122.tar.bz2
RUN tar jxvf mono-4.4.0.122.tar.bz2
RUN cd mono-4.4.0 && ./configure --prefix=/usr && make && make install

RUN apt-get update
RUN apt-get -y upgrade
RUN wget linuxdot.net/down/jexus-5.8.1.tar.gz
RUN tar -zxvf jexus-5.8.1.tar.gz
RUN ./jexus-5.8.1/install
RUN rm jexus-5.8.1.tar.gz

ENV SITE_CONF /usr/jexus/siteconf

COPY default $SITE_CONF/default

EXPOSE 80

#RUN apt-get autoremove -y --purge build-essential automake autoconf bison gettext libtool$

RUN apt-get -y install vim
#CMD /usr/jexus/jws start && tail -f

結尾類似下面就代表成功了。

···
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/ex (ex) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/editor (editor) in auto mode
Processing triggers for libc-bin (2.19-0ubuntu6.7) ...
 ---> 48d13a183661
Removing intermediate container 8b7d3f4b1198
Successfully built 48d13a183661

但是運行起來又有了新問題:

System.InvalidOperationException
The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Areas/HelpPage/Views/Help/Index.aspx
~/Areas/HelpPage/Views/Help/Index.ascx
~/Areas/HelpPage/Views/Shared/Index.aspx
~/Areas/HelpPage/Views/Shared/Index.ascx
~/Views/Help/Index.aspx
~/Views/Help/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Areas/HelpPage/Views/Help/Index.cshtml
~/Areas/HelpPage/Views/Help/Index.vbhtml
~/Areas/HelpPage/Views/Shared/Index.cshtml
~/Areas/HelpPage/Views/Shared/Index.vbhtml
~/Views/Help/Index.cshtml
~/Views/Help/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml

Description: HTTP 500.Error processing request.
Details: Non-web exception. Exception origin (name of application or object): System.Web.Mvc.
Exception stack trace:
  at System.Web.Mvc.ViewResult.FindView (System.Web.Mvc.ControllerContext context) <0x4086a8e0 + 0x002fb> in <filename unknown>:0 
  at System.Web.Mvc.ViewResultBase.ExecuteResult (System.Web.Mvc.ControllerContext context) <0x4086a630 + 0x000fc> in <filename unknown>:0 
  at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult (System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ActionResult actionResult) <0x4083a390 + 0x0001d> in <filename unknown>:0 
  at System.Web.Mvc.ControllerActionInvoker+<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17 () <0x4083a310 + 0x0001f> in <filename unknown>:0 
  at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter (IResultFilter filter, System.Web.Mvc.ResultExecutingContext preContext, System.Func`1 continuation) <0x4083a030 + 0x000d7> in <filename unknown>:0 

 

 

待續···

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM