背景
在上一篇文章安裝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項目部署到麒麟系統上,我預計到又是一段打怪路程,通關後,我會繼續將通關記錄分享出來。
最後曬下截圖: