最近在V站上看到一個外賣推廣的小程序,意思大概是相似淘寶聯盟那種,別人走本身的連接後,本身能夠抽取大概4%-6%的提成。以爲還蠻有意思的,一開始開源的是靜態頁面寫死的,因此我這邊用.Net Core寫了個簡單的後臺。html
左邊是無後臺的,右邊紅色框是後臺配置的。固然功能是很簡單的,主要是記錄發佈到Ubuntu18.4的時候遇到的問題與解決辦法。linux
寶塔Linux面板是提高運維效率的服務器管理軟件,支持一鍵LAMP/LNMP/集羣/監控/網站/FTP/數據庫/JAVA等100多項服務器管理功能。nginx
這裏節省時間直接使用寶塔面板了,這個真的是太方便了,哈哈。安裝也很是簡單。git
由於我使用的是Ubuntu,安裝腳本github
wget -O install.sh http://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh
web
其餘版本請參考官方文檔:https://www.bt.cn/download/linux.html數據庫
安裝完成後會顯示登陸地址、用戶名、密碼信息。登陸後瀏覽器將彈出推薦安裝套件,爲方便直接一鍵安裝LNMP。ubuntu
微軟官方文檔:https://docs.microsoft.com/zh-cn/dotnet/core/install/linux-ubuntu小程序
由於我使用的18.04,因此找到對應文檔。瀏覽器
使用 APT 進行安裝可經過幾個命令來完成。 安裝 .NET 以前,請運行如下命令,將 Microsoft 包簽名密鑰添加到受信任密鑰列表,並添加包存儲庫。
打開終端並運行如下命令:
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
.NET SDK 使你能夠經過 .NET 開發應用。 若是安裝 .NET SDK,則無需安裝相應的運行時。 若要安裝 .NET SDK,請運行如下命令:
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
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
:
sudo apt-get install -y dotnet-runtime-5.0
其實上述就是照搬微軟的官方文檔,官方文檔仍是寫的很清楚的。
我一開始目標運行時選擇的Linux-64,可是出現了這樣的錯誤`錯誤 NU1605: 檢測到包降級: XXXXXXXXXXXXX 從 4.3.0 降級到 XXXXXXXXXXXXX。直接從項目引用包以選擇不一樣版本。
經過查看微軟官方文檔: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:
<PackageReference Include="Microsoft.NETCore.Targets" Version="3.0.0" PrivateAssets="all" />
就是添加引用,但實際上你要保證全部項目的包引用版本是一致的。
另外一種方法
發佈的時候目標運行時直接選擇可移植吧~
在文件 wwwroot新建項目文件夾,將本地發佈文件打包拷貝至服務器解壓。
在服務器上終端命令進入部署文件所在目錄,而後使用dotnet命令啓動服務:
dotnet XXXXXX.Admin.dll --urls "http://localhost:5000"
如今咱們還不能直接訪問到咱們新部署項目,須要使用Nginx設置反向代理,將特定的端口代理到http://localhost:5000
,這一步能夠經過寶塔面板來完成,步驟以下:
在寶塔面板上新建一個網站,設置爲靜態網站便可,並綁定好域名。
在剛纔新建的網站中設置反向代理,目標URL填寫http://localhost:5000便可,發送域名localhost
瀏覽器正式可訪問項目,此處可能須要重啓一下。
如今還有個問題,就是當咱們關閉xShell等SSH工具的時候服務進程也會中止運行,咱們可以使用 Supervisor 守護進程運行。
- 在寶塔面板上安裝Supervisor
- 添加守護進程(用戶建議選擇www,不要使用root)
錯誤 NU1605: 檢測到包降級: XXXXXXXXXXXXX 從 4.3.0 降級到 XXXXXXXXXXXXX。直接從項目引用包以選擇不一樣版本
這個問題一開始我按照官方文檔修改了,實際仍是不能夠。因此我選擇了可移植髮布的。而我在寫這篇文章的時候又能夠了。
驗證碼我使用了
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一鍵命令
sudo curl https://raw.githubusercontent.com/stulzq/awesome-dotnetcore-image/master/install/ubuntu.sh|sh
指定端口啓動
修改
Program.cs
增長代碼
.ConfigureAppConfiguration(builder => { //dotnet test.dll --urls "http://*:5000;https://*:5001" builder.AddCommandLine(args);//設置添加命令行 })完整代碼
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<Startup>(); });
驗證碼生成代碼
驗證碼生成代碼應該是蠻多的,我把個人分享下
using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; namespace XXX.Util { public static class ValidateCodeHelper { /// <summary> /// 驗證碼的最大長度 /// </summary> public static int MaxLength => 10; /// <summary> /// 驗證碼的最小長度 /// </summary> public static int MinLength => 1; /// <summary> /// 生成驗證碼 /// </summary> /// <param name="length">指定驗證碼的長度</param> /// <returns></returns> 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; } /// <summary> /// 獲得驗證碼圖片的長度 /// </summary> /// <param name="validateNumLength">驗證碼的長度</param> /// <returns></returns> public static int GetImageWidth(int validateNumLength) { return (int)(validateNumLength * 12.0); } /// <summary> /// 獲得驗證碼的高度 /// </summary> /// <returns></returns> public static double GetImageHeight() { return 22.5; } //C# MVC 升級版 /// <summary> /// 建立驗證碼的圖片 /// </summary> /// <param name="validateCode">驗證碼</param> 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,受不了。可是真的去使用了,去探索了,嗯,真香~