1. 程式人生 > >Linux(寶塔)部署.Net Core完整記錄

Linux(寶塔)部署.Net Core完整記錄

## 前言 最近在V站上看到一個外賣推廣的小程式,意思大概是類似淘寶聯盟那種,別人走自己的連結後,自己可以抽取大概4%-6%的提成。覺得還蠻有意思的,一開始開源的是靜態頁面寫死的,所以我這邊用.Net Core寫了個簡單的後臺。 左邊是無後臺的,右邊紅色框是後臺配置的。當然功能是很簡單的,主要是記錄釋出到Ubuntu18.4的時候遇到的問題與解決辦法。
· · ·
## 安裝寶塔 > 寶塔Linux面板是提升運維效率的伺服器管理軟體,支援一鍵LAMP/LNMP/叢集/監控/網站/FTP/資料庫/JAVA等100多項伺服器管理功能。 這裡節省時間直接使用寶塔面板了,這個真的是太方便了,哈哈。安裝也非常簡單。 因為我使用的是Ubuntu,安裝指令碼 `wget -O install.sh http://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh` 其他版本請參考官方文件:https://www.bt.cn/download/linux.html 安裝完成後會顯示登入地址、使用者名稱、密碼資訊。登入後瀏覽器將彈出推薦安裝套件,為方便直接一鍵安裝LNMP。 ## 安裝.NetCore SDK 3.1 >
微軟官方文件:https://docs.microsoft.com/zh-cn/dotnet/core/install/linux-ubuntu 因為我使用的18.04,所以找到對應文件。 使用 APT 進行安裝可通過幾個命令來完成。 安裝 .NET 之前,請執行以下命令,將 Microsoft 包簽名金鑰新增到受信任金鑰列表,並新增包儲存庫。 開啟終端並執行以下命令: ```bash wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb ``` ### 安裝 SDK .NET SDK 使你可以通過 .NET 開發應用。 如果安裝 .NET SDK,則無需安裝相應的執行時。 若要安裝 .NET SDK,請執行以下命令: ```bash sudo apt-get update; \ sudo apt-get install -y apt-transport-https && \ sudo apt-get update && \ sudo apt-get install -y dotnet-sdk-3.1 ``` ### 安裝執行時 ```bash sudo apt-get update; \ sudo apt-get install -y apt-transport-https && \ sudo apt-get update && \ sudo apt-get install -y aspnetcore-runtime-3.1 ``` 作為 ASP.NET Core 執行時的一種替代方法,你可以安裝不包含 ASP.NET Core 支援的 .NET 執行時:將上一命令中的 `aspnetcore-runtime-5.0` 替換為 `dotnet-runtime-5.0`: ```bash sudo apt-get install -y dotnet-runtime-5.0 ``` 其實上述就是照搬微軟的官方文件,官方文件還是寫的很清楚的。 ## 釋出.NetCore專案 我一開始目標執行時選擇的Linux-64,但是出現了這樣的錯誤`錯誤 NU1605: 檢測到包降級: XXXXXXXXXXXXX 從 4.3.0 降級到 XXXXXXXXXXXXX。直接從專案引用包以選擇不同版本。 ![image-20201207114647335](https://cdn.jsdelivr.net/gh/jellydong/img/images/image-20201207114647335.png) 通過檢視微軟官方文件:https://docs.microsoft.com/zh-cn/nuget/reference/errors-and-warnings/nu1605 ***問題***當在 .NET Core 3.0 或更高版本的專案中同時引用時,與 .NET Core 1.0 和1.1 隨附的某些包組合不相容。 問題包通常以或開頭 `System.` `Microsoft.` ,並具有4.0.0 和4.3.1 之間的版本號。 在這種情況下,降級訊息將具有從執行時開始的包。 依賴關係鏈。 ***解決方案***若要解決此問題,請新增以下 PackageReference: ```xml
``` 就是新增引用,但實際上你要保證所有專案的包引用版本是一致的。 ***另一種方法*** > 釋出的時候目標執行時直接選擇可移植吧~ ## 寶塔面板釋出.Net Core專案,並啟動專案 在檔案 wwwroot新建專案資料夾,將本地釋出檔案打包拷貝至伺服器解壓。 在伺服器上終端命令進入部署檔案所在目錄,然後使用dotnet命令啟動服務: ``` bash dotnet XXXXXX.Admin.dll --urls "http://localhost:5000" ``` ![image-20201207115503272](https://cdn.jsdelivr.net/gh/jellydong/img/images/image-20201207115503272.png) ## Nginx設定反代訪問 現在我們還不能直接訪問到我們新部署專案,需要使用Nginx設定反向代理,將特定的埠代理到`http://localhost:5000`,這一步可以通過寶塔面板來完成,步驟如下: >
* 在寶塔面板上新建一個網站,設定為靜態網站即可,並繫結好域名。 > > * 在剛才新建的網站中設定反向代理,目標URL填寫http://localhost:5000即可,傳送域名localhost ![image-20201207115748843](https://cdn.jsdelivr.net/gh/jellydong/img/images/image-20201207115748843.png) ![image-20201207115850382](https://cdn.jsdelivr.net/gh/jellydong/img/images/image-20201207115850382.png) 瀏覽器正式可訪問專案,此處可能需要重啟一下。 ## 使用 Supervisor 守護程序 > 現在還有個問題,就是當我們關閉xShell等SSH工具的時候服務程序也會停止執行,我們可使用 Supervisor 守護程序執行。 > > * 在寶塔面板上安裝Supervisor > * 新增守護程序(使用者建議選擇www,不要使用root) ![image-20201207120537225](https://cdn.jsdelivr.net/gh/jellydong/img/images/image-20201207120537225.png) ## 問題 ### 問題1 > `錯誤 NU1605: 檢測到包降級: XXXXXXXXXXXXX 從 4.3.0 降級到 XXXXXXXXXXXXX。直接從專案引用包以選擇不同版本` > > 這個問題一開始我按照官方文件修改了,實際還是不可以。所以我選擇了可移植髮布的。而我在寫這篇文章的時候又可以了。 ## 問題2 > 驗證碼我使用了`System.Drawing`,不過在Linux下的話,這個是無法顯示的。 > > ***解決辦法*** > > `System.Drawing.Common` 元件提供對GDI+圖形功能的訪問。它是依賴於GDI+的,那麼在Linux上它如何使用GDI+,因為Linux上是沒有GDI+的。Mono 團隊使用C語言實現了GDI+介面,提供對非Windows系統的GDI+介面訪問能力(個人認為是模擬GDI+,與系統圖像介面對接),這個就是 `libgdiplus`。進而可以推測 `System.Drawing.Common` 這個元件實現時,對於非Windows系統肯定依賴了 `ligdiplus` 這個元件。如果我們當前系統不存在這個元件,那麼自然會報錯,找不到它,安裝它即可解決。 > >***Ubuntu一鍵命令*** > > ```bash > sudo curl https://raw.githubusercontent.com/stulzq/awesome-dotnetcore-image/master/install/ubuntu.sh|sh > ``` > > 參考:https://www.cnblogs.com/stulzq/p/10172550.html ## 問題3 > 指定埠啟動 > > 修改`Program.cs` > > 增加程式碼 > > ```csharp > .ConfigureAppConfiguration(builder => > { > //dotnet test.dll --urls "http://*:5000;https://*:5001" > builder.AddCommandLine(args);//設定新增命令列 > }) > ``` > > 完整程式碼 > > ```csharp > public static IHostBuilder CreateHostBuilder(string[] args) => > Host.CreateDefaultBuilder(args) > //將預設ServiceProviderFactory指定為AutofacServiceProviderFactory https://autofaccn.readthedocs.io/en/latest/integration/aspnetcore.html#asp-net-core-3-0-and-generic-hosting > .UseServiceProviderFactory(new AutofacServiceProviderFactory()) > .ConfigureAppConfiguration(builder => > { > //dotnet test.dll --urls "http://*:5200;https://*:5100" > builder.AddCommandLine(args);//設定新增命令列 > }) > .ConfigureWebHostDefaults(webBuilder => > { > webBuilder.UseStartup(); > }); > ``` ## 問題4 >驗證碼生成程式碼 > >驗證碼生成程式碼應該是蠻多的,我把我的分享下 > >```csharp >using System; >using System.Drawing; >using System.Drawing.Drawing2D; >using System.Drawing.Imaging; >using System.IO; > >namespace XXX.Util >{ > public static class ValidateCodeHelper > { > /// > /// 驗證碼的最大長度 > /// > public static int MaxLength => 10; > > /// > /// 驗證碼的最小長度 > /// > public static int MinLength => 1; > > /// > /// 生成驗證碼 > /// > /// 指定驗證碼的長度 > /// > public static string CreateValidateCode(int length) > { > int[] randMembers = new int[length]; > int[] validateNums = new int[length]; > string validateNumberStr = ""; > //生成起始序列值 > int seekSeek = unchecked((int)DateTime.Now.Ticks); > Random seekRand = new Random(seekSeek); > int beginSeek = (int)seekRand.Next(0, Int32.MaxValue - length * 10000); > int[] seeks = new int[length]; > for (int i = 0; i < length; i++) > { > beginSeek += 10000; > seeks[i] = beginSeek; > } > //生成隨機數字 > for (int i = 0; i < length; i++) > { > Random rand = new Random(seeks[i]); > int pownum = 1 * (int)Math.Pow(10, length); > randMembers[i] = rand.Next(pownum, Int32.MaxValue); > } > //抽取隨機數字 > for (int i = 0; i < length; i++) > { > string numStr = randMembers[i].ToString(); > int numLength = numStr.Length; > Random rand = new Random(); > int numPosition = rand.Next(0, numLength - 1); > validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1)); > } > //生成驗證碼 > for (int i = 0; i < length; i++) > { > validateNumberStr += validateNums[i].ToString(); > } > return validateNumberStr; > } > /// > /// 得到驗證碼圖片的長度 > /// > /// 驗證碼的長度 > /// > public static int GetImageWidth(int validateNumLength) > { > return (int)(validateNumLength * 12.0); > } > /// > /// 得到驗證碼的高度 > /// > /// > public static double GetImageHeight() > { > return 22.5; > } > > > //C# MVC 升級版 > /// > /// 建立驗證碼的圖片 > /// > /// 驗證碼 > public static byte[] CreateValidateGraphic(string validateCode) > { > Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22); > Graphics g = Graphics.FromImage(image); > try > { > //生成隨機生成器 > Random random = new Random(); > //清空圖片背景色 > g.Clear(Color.White); > //畫圖片的干擾線 > for (int i = 0; i < 25; i++) > { > int x1 = random.Next(image.Width); > int x2 = random.Next(image.Width); > int y1 = random.Next(image.Height); > int y2 = random.Next(image.Height); > g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); > } > Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic)); > LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), > Color.Blue, Color.DarkRed, 1.2f, true); > g.DrawString(validateCode, font, brush, 3, 2); > //畫圖片的前景干擾點 > for (int i = 0; i < 100; i++) > { > int x = random.Next(image.Width); > int y = random.Next(image.Height); > image.SetPixel(x, y, Color.FromArgb(random.Next())); > } > //畫圖片的邊框線 > g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1); > //儲存圖片資料 > MemoryStream stream = new MemoryStream(); > image.Save(stream, ImageFormat.Jpeg); > //輸出圖片流 > return stream.ToArray(); > } > finally > { > g.Dispose(); > image.Dispose(); > } > } > } >} > >``` > > ## 總結 其實就是一篇流水賬,記錄了釋出的過程和遇到的問題及解決辦法。之前伺服器一直是使用的WinServer,因為熟悉。勇於嘗試並去解決問題,慢慢進步~ 大學裡也學過Linux,受不了。但是真的去使用了,去探索了,嗯