背景
在上一篇文章安装dotnet core,已经安装好dotnet core了。以前只是安装成功了dotnet, 输入dotnet --info,能够确认安装成功了,可是在运行代码时,仍是报错了,本章记录在部署好dotnet core后,到能运行控制台程序当中的错误。html
首先将项目用vs发布一下,而后把文件放到中标麒麟的系统上,在文件夹打开终端,执行 dotnet **.dll,结果以下:前端
[root@gumis02 PublishOutput]# dotnet Beyondbit.ConsoleFrameworkNetStandard.IntegrationTests.dll Failed to load \ufffd=l, error: libunwind.so.8: cannot open shared object file: No such file or directory Failed to bind to CoreCLR at '/home/dotnet/shared/Microsoft.NETCore.App/2.0.7/libcoreclr.so' [root@gumis02 PublishOutput]#
修复此问题的解决方案是安装 libunwindvue
libunwind的源代码如今已经托管到github上了,libunwind github 地址
我安装的是最新版1.2.1, 输入下面命令安装:linux
wget https://github.com/libunwind/libunwind/releases/download/v1.2.1/libunwind-1.2.1.tar.gz tar -xf libunwind-1.2.1.tar.gz cd libunwind-1.2.1 CFLAGS=-fPIC ./configure #添加编译参数 make CFLAGS=-fPIC make CFLAGS=-fPIC install
安装成功后,再执行dotnet **.dll,会发现依然报错ibunwind.so.8: cannot open shared object file: No such file or directory
在输入如下命令修复:git
[root@gumis02 dotnet]# find / -name libunwind.so.8 /home/.Trash-0/files/libunwind-1.2.1/src/.libs/libunwind.so.8 /home/NetCoreSdk/libunwind-1.2.1/src/.libs/libunwind.so.8 /usr/local/lib/libunwind.so.8 [root@gumis02 dotnet]# ln -s /usr/local/lib/libunwind.so.8 /lib64/ [root@gumis02 dotnet]# ln -s /usr/local/lib/libunwind.so.8 /lib [root@gumis02 dotnet]# find / -name libunwind-x86_64.so.8 /home/.Trash-0/files/libunwind-1.2.1/src/.libs/libunwind-x86_64.so.8 /home/NetCoreSdk/libunwind-1.2.1/src/.libs/libunwind-x86_64.so.8 /usr/local/lib/libunwind-x86_64.so.8 [root@gumis02 dotnet]# ln -s /usr/local/lib/libunwind-x86_64.so.8 /lib64/ [root@gumis02 dotnet]# ln -s /usr/local/lib/libunwind-x86_64.so.8 /lib
输入后,再执行dotnet **.dll,发现上面的问题已经消失。可是出现新的错误提示:github
FailFast: Couldn't find a valid ICU package installed on the system. Set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support. at System.Environment.FailFast(System.String) at System.Globalization.GlobalizationMode.GetGlobalizationInvariantMode() at System.Globalization.GlobalizationMode..cctor() at System.Globalization.CultureData.CreateCultureWithInvariantData() at System.Globalization.CultureData.get_Invariant() at System.Globalization.CultureData.GetCultureData(System.String, Boolean) at System.Globalization.CultureInfo.InitializeFromName(System.String, Boolean) at System.Globalization.CultureInfo.Init() at System.Globalization.CultureInfo..cctor() at System.StringComparer..cctor() at System.AppDomainSetup.SetCompatibilitySwitches(System.Collections.Generic.IEnumerable`1<System.String>) at System.AppDomain.PrepareDataForSetup(System.String, System.AppDomainSetup, System.Security.Policy.Evidence, System.Security.Policy.Evidence, IntPtr, System.String, System.String[], System.String[]) \u5df2\u653e\u5f03 (core dumped) [root@gumis02 PublishOutput]#
下一步,准备修复这个错误.web
查找资料显示,这是NET Core 全球化的模式,可见微软的文章 NET Core Globalization Invariant Modedocker
Globalization rules and the data that represents those rules frequently change, often due to country-specific policy changes (for example, changes in currency symbol, sorting behavior or time zones). Developers expect globalization behavior to always be current and for their applications to adapt to new data over time. In order to keep up with those changes, .NET Core (and the .NET Framework, too) depends on the underlying OS to keep up with these changes.数据库
Relying on the underlying OS for globalization data has the following benefits:json
Globalization support has the following potential challenges for applications:
Note: On Linux, .NET Core relies on globalization data from ICU. For example, .NET Core Linux Docker images install this component. Globalization data is available on Windows and macOS as part of their base installs.
上文提到依赖 ICU Package,可点击连接去查看。
有两种解决方案:
"configProperties": { "System.Globalization.Invariant": true }
完整的在runtimeconfig.json 以下:
{ "runtimeOptions": { "tfm": "netcoreapp2.0", "framework": { "name": "Microsoft.NETCore.App", "version": "2.0.0" }, "configProperties": { "System.Globalization.Invariant": true } } }
注意
这种方式,证实了是能够解决问题的,可是他开启了Globalization.Invariant Mode 模式,在简单的应用下,程序能够正常运行,可是在遇到复杂的应用颇有可能会遇到一个异常,System.ArgumentNullException: SafeHandle cannot be null,见我正式项目的运行结果,这个异常在github上有不少人提到,如:
个人测试项目就是用了log4net致使的,目前net corefx团队收到了反馈已经在着手解决了。要想终极解决此问题,须要用如下第二种方式来解决,安装 ICU Package模块。
咱们使用源码的方式安装icu. 我选择的是59.1版本,输入如下命令:
wget http://download.icu-project.org/files/icu4c/59.1/icu4c-59_1-src.tgz tar -xzvf icu4c-59_1-src.tgz cd icu/source ./configure --prefix=/usr/local/icu make make install
参看是否安装成功:
[root@gumis02 ~]# icu-config --version 59.1 [root@gumis02 ~]# icuinfo icuinfo: error while loading shared libraries: libicutu.so.59: cannot open shared object file: No such file or directory
看到安装成功了,可是查看具体信息会提示缺乏 libicutu.so.59,其余缺乏的dll,一样处理。
输入如下命令查找,并映射so文件:
[root@gumis02 ~]# find / -name libicutu.so.59 /home/NetCoreSdk/icu/source/lib/libicutu.so.59 /home/NetCoreSdk/icu2/source/lib/libicutu.so.59 /usr/lib/libicutu.so.59 /usr/local/icu/lib/libicutu.so.59 [root@gumis02 ~]# ln -s /usr/local/icu/lib/libicutu.so.59 /lib64/ [root@gumis02 ~]# ln -s /usr/local/icu/lib/libicui18n.so.59 /lib64/ [root@gumis02 ~]# ln -s /usr/local/icu/lib/libicuuc.so.59 /lib64/ [root@gumis02 ~]# ln -s /usr/local/icu/lib/libicudata.so.59 /lib64/ [root@gumis02 ~]# ln -s /usr/local/icu/lib/libicudata.so.59 /lib64/ [root@gumis02 ~]# icuinfo <icuSystemParams type="icu4c"> <param name="copyright"> Copyright (C) 2016 and later: Unicode, Inc. and others. License & terms of use: http://www.unicode.org/copyright.html </param> <param name="product">icu4c</param> <param name="product.full">International Components for Unicode for C/C++</param> <param name="version">59.1</param> <param name="version.unicode">9.0</param> <param name="platform.number">4000</param> <param name="platform.type">Linux</param> <param name="locale.default">zh_CN</param> <param name="locale.default.bcp47">zh-CN</param> <param name="converter.default">UTF-8</param> <param name="icudata.name">icudt59l</param> <param name="icudata.path"></param> <param name="cldr.version">31.0.1</param> <param name="tz.version">2017b</param> <param name="tz.default">PRC</param> <param name="cpu.bits">64</param> <param name="cpu.big_endian">0</param> <param name="os.wchar_width">4</param> <param name="os.charset_family">0</param> <param name="os.host">x86_64-unknown-linux-gnu</param> <param name="build.build">x86_64-unknown-linux-gnu</param> <param name="build.cc">gcc</param> <param name="build.cxx">g++</param> <param name="uconfig.internal_digitlist">1</param> <param name="uconfig.have_parseallinput">1</param> <param name="uconfig.format_fastpaths_49">1</param> </icuSystemParams> ICU Initialization returned: U_ZERO_ERROR Plugins are disabled.
参考:
install ICU-61.1
安装完成后,再测试正式的项目,执行成功了,数据插入到数据库了。
采用配置了 runtimeconfig.json中添加如下配置
"configProperties": { "System.Globalization.Invariant": true }
HelloWorld程序运行测试:
Microsoft .NET Core Shared Framework Host Version : 2.0.7 Build : 2d61d0b043915bc948ebf98836fefe9ba942be11 [root@gumis02 ConsoleTest2]# dotnet ConsoleApp2.dll FailFast: Couldn't find a valid ICU package installed on the system. Set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support. at System.Environment.FailFast(System.String) at System.Globalization.GlobalizationMode.GetGlobalizationInvariantMode() at System.Globalization.GlobalizationMode..cctor() at System.Globalization.CultureData.CreateCultureWithInvariantData() at System.Globalization.CultureData.get_Invariant() at System.Globalization.CultureData.GetCultureData(System.String, Boolean) at System.Globalization.CultureInfo.InitializeFromName(System.String, Boolean) at System.Globalization.CultureInfo.Init() at System.Globalization.CultureInfo..cctor() at System.StringComparer..cctor() at System.AppDomainSetup.SetCompatibilitySwitches(System.Collections.Generic.IEnumerable`1<System.String>) at System.AppDomain.PrepareDataForSetup(System.String, System.AppDomainSetup, System.Security.Policy.Evidence, System.Security.Policy.Evidence, IntPtr, System.String, System.String[], System.String[]) \u5df2\u653e\u5f03 (core dumped) [root@gumis02 ConsoleTest2]# dotnet ConsoleApp2.dll Hello World! [root@gumis02 ConsoleTest2]#
在runtimeconfig.json中添加如下配置便可,不想纠结原理的就使用这种方式便可:
"configProperties": { "System.Globalization.Invariant": true }
上面的这种方式,我使用helloworld程序是能正常运行的,可是在正式的项目中,用到了log4net,运行的话,会报其余的错误:
[root@gumis02 PublishOutput]# dotnet Beyondbit.ConsoleFrameworkNetStandard.IntegrationTests.dll Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentNullException: SafeHandle cannot be null. Parameter name: pHandle at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument, ExceptionResource resource) at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success) at Interop.GlobalizationInterop.GetSortKey(SafeSortHandle sortHandle, String str, Int32 strLength, Byte* sortKey, Int32 sortKeyLength, CompareOptions options) at System.Globalization.CompareInfo.GetHashCodeOfStringCore(String source, CompareOptions options, Boolean forceRandomizedHashing, Int64 additionalEntropy) at System.Collections.Hashtable.GetHash(Object key) at System.Collections.Hashtable.InitHash(Object key, Int32 hashsize, UInt32& seed, UInt32& incr) at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add) at System.Collections.Hashtable.set_Item(Object key, Object value) at log4net.Core.LevelMap.Add(Level level) at log4net.Repository.LoggerRepositorySkeleton.AddBuiltinLevels() at log4net.Repository.LoggerRepositorySkeleton..ctor(PropertiesDictionary properties) at log4net.Repository.Hierarchy.Hierarchy..ctor(PropertiesDictionary properties, ILoggerFactory loggerFactory) --- End of inner exception stack trace --- at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at log4net.Core.DefaultRepositorySelector.CreateRepository(String repositoryName, Type repositoryType) at log4net.Core.DefaultRepositorySelector.CreateRepository(Assembly repositoryAssembly, Type repositoryType, String repositoryName, Boolean readAssemblyAttributes) at log4net.Core.LoggerManager.GetLogger(Assembly repositoryAssembly, String name) at log4net.LogManager.GetLogger(Type type) at Beyondbit.Framework.Core.Proxy.Proxy.SetSessionToContext(ISession session) in E:\\u5de5\u4f5c\u533a\03 \u4e92\u8054\u7f51\00 Beyondbit Infrastructure\\u5f00\u53d1\u6846\u67b6\3.0\Beyondbit.Framework\Core\Proxy\Proxy.cs:line 117 at Beyondbit.Framework.Core.Proxy.Proxy.CreateClassProxy[T]() in E:\\u5de5\u4f5c\u533a\03 \u4e92\u8054\u7f51\00 Beyondbit Infrastructure\\u5f00\u53d1\u6846\u67b6\3.0\Beyondbit.Framework\Core\Proxy\Proxy.cs:line 82 at Beyondbit.Framework.Core.Proxy.Proxy.CreateObject[T]() in E:\\u5de5\u4f5c\u533a\03 \u4e92\u8054\u7f51\00 Beyondbit Infrastructure\\u5f00\u53d1\u6846\u67b6\3.0\Beyondbit.Framework\Core\Proxy\Proxy.cs:line 55 at Beyondbit.ConsoleFrameworkNetStandard.IntegrationTests.Program.Insert() in E:\\u5de5\u4f5c\u533a\03 \u4e92\u8054\u7f51\00 Beyondbit Infrastructure\\u5f00\u53d1\u6846\u67b6\3.0\Test\Integration\ConsoleFrameworkNetStandard\Program.cs:line 22 at Beyondbit.ConsoleFrameworkNetStandard.IntegrationTests.Program.Main(String[] args) in E:\\u5de5\u4f5c\u533a\03 \u4e92\u8054\u7f51\00 Beyondbit Infrastructure\\u5f00\u53d1\u6846\u67b6\3.0\Test\Integration\ConsoleFrameworkNetStandard\Program.cs:line 14 \u5df2\u653e\u5f03 (core dumped) [root@gumis02 PublishOutput]#
能够看到错误的调用堆栈,是由log4net运行出来的,这个颇有多是里面须要增长全局资源文件,由于看到了System.Globalization命名空间,不过呢,已经能看到了正常的net 错误堆栈,能够证实dotnet 已经在中标麒麟的操做系统上能运行了。
这个异常产生的缘由我在上面已经说明了,要解决这个问题,不能开启Globalization.Invariant,必须讲他设置成false,同时安装ICU Packet解决
在runtimeconfig.json中添加如下配置便可,不想纠结原理的就使用这种方式便可:
"configProperties": { "System.Globalization.Invariant": false }
执行结果:
[root@gumis02 PublishOutput]# dotnet Beyondbit.ConsoleFrameworkNetStandard.IntegrationTests.dll 用户插入成功 [root@gumis02 PublishOutput]#
dotnet core 2.0 在真实项目上,还有不少的未知,还等待我去解决和探索。 Keep going.
总结:
通过一个星期的摸爬滚打终于在中标麒麟Linux系统上成功的运行了dotnet core 正式的项目,而不是helloworld程序。心力交瘁中也收获了不少东西,在这一个星期中,我一个linux盲,也掌握了不少linux命令,如:mkdir,ln, find,ll,ldd 等等。固然用了一个星期的时间,主要仍是本身两方面的问题:
- 对linux不熟悉,基本是linux盲
- 对net core 底层的编译知识还不熟悉,在摸索当中
后续还要增强两方面的学习,学无止境
后续
成功的是控制台程序,下一步开始把作好的dotnet core web api + 前端 vuejs项目部署到麒麟系统上,我预计到又是一段打怪路程,通关后,我会继续将通关记录分享出来。
最后晒下截图: