上一篇文章介绍了如何将开发好的 Asp.Net Core 应用程序部署到 IIS,且学习了进程内托管和进程外托管的区别;接下来就要说说应用 Asp.Net Core 的特性(跨平台),将 .NetCore 部署到 Linux 中,主流的 Linux 有多个版本的操作系统,这里以 Centos-7.5 为例子,其它版本的操作系统下的部署基本都是大同小异的,除了了一些命令上的区别。
在 Linux 上部署 .Net Core 应用程序,通常的做法是使用托管宿主,早在 1.0.4 的时代,曾经推荐的做法是使用自托管,即 Kestrel,后来官方主力推荐使用 Supervisor 进行托管部署;当然,还有如今最流行的 Docker 部署,但是 Docker 部署不在本文讨论范围,这次我们主要讲讲怎么使用 “Kestrel” 和 “Supervisor” 进行部署。
为了演示部署,我专门到 Azure 上申请了 1 元使用套餐,创建了一个 Centos-7.5 的虚拟机,申请过程非常轻松愉快,支付 1 元即可完成 1500 元的信用额度,使用期限 30 天,童叟无欺,推荐大家申请,用作测试学习的机器。
花了几分钟,机器拿到了,感谢 Azure 的友情支持
SSH 连接到虚拟机,他是长这个样子的,输入命令 cat /etc/redhat-release 查看版本
大家拿到一台机器的时候,一定要确认一下操作系统的版本,因为 ubuntu 和 centos 下的有些命令是不同的,比如 ubuntu 使用 apt-get,而 centos 使用 yun
好了,机器已经拿到,系统已经确认,下面的工作首先就是要在 Centos 上安装 .net core,因为是 Azure ,我抱着幻想输入 dotnet --version,果然,提示命令不存在,这很工业标准。
好的,没问题,我们就按照 https://dotnet.microsoft.com/learn/web/aspnet-hello-world-tutorial/install 的指引进行安装即可,依次输入下面的命令
sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
sudo yum update
sudo yum install dotnet-sdk-2.2
因为现在我们登录的账号不是 root,所以执行命令期间可能会提示输入密码,照做即可,由于是新机器第一次进行 yum update ,可能各种依赖比较多,请耐心等待安装完成。如果是第一次使用 Linux 的同学,请把 Linux 想象成 Windows 下的 dos 系统操作,这样就可以实现平滑过渡了。
安装完成,输入 dotnet --version 输出下面的信息,证明安装成功了
配置服务运行的端口有两种方式,之前的文章介绍了使用 hosting.json 文件的方式,这里演示为了方便,因为 linux 下要配置防火墙等操作会把新手搞懵逼,我们直接的代码中指定 80 端口,代码如下
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options =>
{
options.Listen(IPAddress.Parse("0.0.0.0"), 80);
})
.UseStartup<Startup>();
}
非常简洁的代码,仅仅使用 UseKestrel 就可以配置侦听地址和端口,如果有多块网卡的朋友,注意最好还是指定 IP 地址。
定位到项目 D:\Learning\Deploy.Linux\Deploy.Linux,输入 cmd 启动命令行,输入以下命令
dotnet publish --runtime centos.7-x64 --framework netcoreapp2.2 --configuration release
执行上述命令后,将会在项目 bin\release\netcoreapp2.2\centos.7-x64\publish 下看到有发布好的项目文件和依赖项目
注意:参数 --runtime 是有固定 RID 的,想了解更多有关 RID 的知识,请移步 .NET Core RID 目录
接下来,在服务器中新建一个文件夹,在控制台中输入命令
sudo mkdir -p /data/sites/demo
// 修改权限为当前登录用户,否则无法上传
sudo chown -R ron:ron /data
将 publish 文件夹上传到服务器上刚才创建好的文件夹 /data/sites/demo 下,我这里使用的是 SecureFx ,简单粗暴,直接复制上传
上传成功后,先不要着急的写服务文件,先测试一下是否可以启动,先使用控制台进行测试,输入命令定位到 publish 文件夹
cd /data/sites/demo/publish
// 启动,因为要侦听端口,而且我们使用的不是 root 用户,这里需要使用 sudo 进行提权,如果提示输入密码,请输入当前登录用户的密码即可
sudo dotnet Deploy.Linux.dll
测试启动成功,上面输出的信息表示,我们的发布是没有问题的,先来了解一下上面的输出信息
// 主机环境:Production
Hosting environment: Production
// 根目录
Content root path: /data/sites/demo/publish
// 侦听地址和端口
Now listening on: http://0.0.0.0:80
// 提示关闭技巧,Ctrl+C 可以关闭此主机
Application started. Press Ctrl+C to shut down.
没有太多的信息,同样的简单明了,实际上,现在我们已经通过 80 端口来访问该站点了,但是作为服务,必须要常驻内存中运行,而不是关闭窗口就停止了站点。
所以,接下来我们就编写一个脚本文件,将该站点托管到 Linux 服务中,这个脚本文件官网有示例,我们可以直接拿过来用,但是首先,我们得先在系统中创建一个服务文件 kestrel-dotnet.service
定位到文件夹 /etc/systemd/system,输入命令
sudo vi kestrel-dotnet.service
// 按 i 将编辑器转换为输入模式
// 将以下内容 copy 到当前编辑器中
[Unit]
Description=Example .NET Web Site running on Centos
[Service]
WorkingDirectory=/data/sites/demo/publish
ExecStart=/usr/bin/dotnet Deploy.Linux.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
[Install]
WantedBy=multi-user.target
// 按 esc 键推出编辑模式,输入命令 :wq! 保存并退出
通过上面这波操作以后,你就得到了一个服务文件 kestrel-dotnet.service,这是一个标准的 Linux 服务配置文件
经过上面的一系列操作,对于还没有接触过 Linux 的同学来说,已经有点疲惫了,再坚持一下,马上就好
现在将创建好的服务文件注册到系统中,然后启动它,依次输入以下命令
// 注册服务
sudo systemctl enable kestrel-dotnet.service
// 启动服务
sudo systemctl start kestrel-dotnet.service
好了,现在访问我们的站点,目前我的站点是: http://139.219.9.102/ 在服务没有到期之前,大家应该都是该地址应该是可以访问的
写到这里,发现文章居然有点长了,对于入门文章来说,这是不合适的,好吧,下一篇再继续介绍使用 Supervisor 进行托管部署 Asp.Net Core 应用程序
演示代码下载: https://github.com/lianggx/EasyAspNetCoreDemo/tree/master/Deploy.Linux
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数