【NetCore-部署】如何在Linux上部署NetCore项目 2020年10月23日 NetCore nginx linux supervisor vsftpd 系统:Centos7 .net core 版本:.net core 3.1 ## 一、安装 .Net Core 运行环境 ### 1.在线安装 我们只是在Linux系统上面部署应用程序,所以只需要安装ASP.NET Core Runtime即可。 安装 .NET 之前,请运行以下命令,将 Microsoft 包签名密钥添加到受信任密钥列表,并添加 Microsoft 包存储库。 打开终端并运行以下命令: ``` sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm ```  更新可供安装的产品: 如下图所示:  最后安装ASP.NET Core 运行时 ``` sudo yum install aspnetcore-runtime-3.1 ``` 如下图所示:  这时就比较考验网速了,如果网速比较快,安装就很快。安装完成以后查看当前环境:  参考微软官方文档: [https://docs.microsoft.com/zh-cn/dotnet/core/install/linux-package-manager-centos7](https://docs.microsoft.com/zh-cn/dotnet/core/install/linux-package-manager-centos7) ### 2.离线安装 如果Linux虚拟机可以连接外网,建议使用上面的方式直接进行安装,如果是在生产环境下该如何安装Runtime呢?下面我们使用微软提供的离线安装包进行安装。首先下载tar.gz的离线包,下载网址: [https://dotnet.microsoft.com/download/dotnet-core/3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) 这里选择Linux对应的架构的离线包下载:  我们首先在Linux上创建一个目录: 如下图所示:  创建完成以后,我们使用Xftp把上面下载的tar.gz离线包上传到刚才创建的目录中:  进入刚才创建的目录,然后把tar.gz文件解压到目录中: ``` tar zxf aspnetcore-runtime-3.1.1-linux-x64.tar.gz -C /var/lib/dotnet ``` 如下图所示:  然后执行下面的命令设置环境变量: ``` export DOTNET_ROOT=/var/lib/dotnet export PATH=$PATH:/var/lib/dotnet ``` 如下图所示:  然后检查环境:  可以看到Runtime已经安装成功了。 注意:这种设置环境变量的方式只对当前会话窗口起作用,在另外的会话窗口就不起作用了,如下图所示:  为了解决这个问题,我们需要创建软链接方式来设置环境变量。 ``` ln -s /var/lib/dotnet/dotnet /usr/local/bin ``` 如下图所示:  创建完软链接以后,就可以在所有会话窗口访问了:  > 如果是使用在线rpm的方式进行安装,不会出现这种问题,所有的会话窗口都可以访问。 ### 部署并启动 web 安装好环境,上传文件之后,进入网站文件夹就可以通过命令启动。 ```shell dotnet WebDemo.dll ```  修改启动IP和端口 ```shell dotnet WebDemo.dll --urls http://*:5000 ``` 如果服务器开启了防火墙,那需要把启动的端口加入到防火墙中 ``` firewall-cmd --zone=public --add-port=5000/tcp --permanent ``` > permanent:这个参数表示永久存在,否则重启防火墙配置就丢失了。  也可以关闭防火墙,生产环境中不建议关闭 ```shell service firewalld stop ``` ## 用Nginx 作为反向代理 ### 安装 Nginx ,并启动 因为默认情况下,Nginx不在CentOS的资源库中,首先要执行下面的命令将Nginx添加到资源库中: ```shell rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm ```  * 安装 ```shell yun install nginx ```  * 启动 ``` systemctl start nginx ```  * 设为开机启动 ```shell systemctl enable nginx ```  * 将80端口加入防火墙并重启防火墙 ``` firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --reload ```  已经可以访问Nginx了  ### 配置 Nginx 进入Nginx的安装目录,然后查看所有文件:  用 vim 打开 `nginx.conf` ``` vim nginx.conf ```  进入 `/etc/nginx/conf.d` 文件夹,一般默认会一个 `default.conf` 文件,用 vim 打开这个文件  修改配置文件 ``` shell server { listen 80; #设置监听端口,http网站默认80 server_name zhandaiban.com; #设置域名地址 client_max_body_size 200m; large_client_header_buffers 4 10m; add_header X-Frame-Options "SAMEORIGIN"; #保护Nginx 免受点击劫持的侵害 add_header X-Content-Type-Options "nosniff"; #可阻止大部分浏览器通过MIME方式探查来自已声明内容类型的响应 location / { root /usr/share/nginx/html; index index.html index.htm; proxy_pass http://localhost:5000; #设置代理地址,这里就可以填写 .net core web 的本地地址了 proxy_set_header Host $host; #配置请求转接头1 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #配置请求转接头2 proxy_set_header X-Forwarded-Proto $scheme; #配置请求转接头3 } } ``` > 加上 `proxy_set_header ` 是为了解决使用Nginx反向代理时 .net core 无法获取访问用户的真实IP地址 。详情: [【NetCore-Debug】使用Nginx反向代理时如何获取真实IP](bear://x-callback-url/open-note?id=C57FD5E9-3A28-48F5-8E28-1070C1983A70-67323-0000F3F4E54030B2) 保存后,用一下命令检查修改是否正确 ``` nginx -t ```  重启 Nginx ``` nginx -s reload ``` ## 二、安装搭建FTP服务器(vsftpd) ### 1、 vsftpd 介绍 ①vsftpd 是以一般身份启动服务,所以对于 Linux 系统的使用权限较低,对于Linux 系统的危害就相对的减低了。此外, vsftpd 亦利用 chroot() 这个函式进行改换根目录的动作,使得系统工具不会被vsftpd 这支服务所误用; ②任何需要具有较高执行权限的 vsftpd 指令均以一支特殊的上层程序( parent process ) 所控制 ,该上层程序享有的较高执行权限功能已经被限制的相当的低,并以不影响Linux 本身的系统为准; ③所有来自 clients 端,想要使用这支上层程序所提供的较高执行权限之vsftpd 指令的需求,均被视为『不可信任的要求』来处理,必需要经过相当程度的身份确认后,方可利用该上层程序的功能。例如chown(), Login 的要求等等动作; ④此外,上面提到的上层程序中,依然使用 chroot() 的功能来限制使用者的执行权限。 ### 2、 通过yum命令安装 ``` shell yum -y install vsftpd ``` ### 3、 修改配置文件 ``` shell cd /etc/vsftpd vim vsftpd.conf ``` vsftpd.conf 文件解析 ``` #是否允许匿名,默认no anonymous_enable=NO #这个设定值必须要为YES 时,在/etc/passwd内的账号才能以实体用户的方式登入我们的vsftpd主机 local_enable=YES #具有写权限 write_enable=YES #本地用户创建文件或目录的掩码 local_umask=022 #当dirmessage_enable=YES时,可以设定这个项目来让vsftpd寻找该档案来显示讯息!您也可以设定其它档名! dirmessage_enable=YES #当设定为YES时,使用者上传与下载日志都会被纪录起来。记录日志与下一个xferlog_file设定选项有关 xferlog_enable=YESxferlog_std_format=YES #上传与下载日志存放路径 xferlog_file=/var/log/xferlog #开启20端口 connect_from_port_20=YES #关于系统安全的设定值: #ascii_download_enable=YES(NO) #如果设定为YES ,那么 client 就可以使用 ASCII 格式下载档案。 #一般来说,由于启动了这个设定项目可能会导致DoS 的攻击,因此预设是NO。 #ascii_upload_enable=YES(NO) #与上一个设定类似的,只是这个设定针对上传而言!预设是NO。 ascii_upload_enable=NO ascii_download_enable=NO #通过搭配能实现以下几种效果: #①当chroot_list_enable=YES,chroot_local_user=YES时,在/etc/vsftpd.chroot_list文件中列出的用户,可以切换到其他目录;未在文件中列出的用户,不能切换到其他目录。 #②当chroot_list_enable=YES,chroot_local_user=NO时,在/etc/vsftpd.chroot_list文件中列出的用户,不能切换到其他目录;未在文件中列出的用户,可以切换到其他目录。 #③当chroot_list_enable=NO,chroot_local_user=YES时,所有的用户均不能切换到其他目录。 #④当chroot_list_enable=NO,chroot_local_user=NO时,所有的用户均可以切换到其他目录。 chroot_local_user=YES chroot_list_enable=YES chroot_list_file=/etc/vsftpd/chroot_list #这个是pam模块的名称,我们放置在/etc/pam.d/vsftpd pam_service_name=vsftpd #当然我们都习惯支持TCP Wrappers的啦! tcp_wrappers=YES #不添加下面这个会报错:500 OOPS: vsftpd: refusing to run with writable root inside chroot() allow_writeable_chroot=YES #ftp的端口号 listen_port=60021 #启动被动式联机(passivemode) pasv_enable=YES #上面两个是与passive mode 使用的 port number 有关,如果您想要使用65400到65410 这 11 个 port 来进行被动式资料的连接,可以这样设定 pasv_min_port=65400 pasv_max_port=65410 #FTP访问目录 local_root=/data/ftp/ ``` ### 4、 添加防火墙开启相关端口 ``` shell #添加主端口 firewall-cmd --permanent --zone=public --add-port=60021/tcp #添加被动端口 firewall-cmd --permanent --zone=public --add-port=65400-65410/tcp #刷新 firewall-cmd --reload ``` 如果测试可以先关闭防火墙 ``` shell systemctl stop firewalld ``` ### 5、 创建FTP用户 添加FTP用户命令:useradd XXX 设置FTP用户密码:passwd XXX ```shell useradd -d /data/ftp/ -s /sbin/nologin ftpuser passwd ftpuser ``` 查看FTP用户是否设置不能通过SSH登录,只能使用FTP ``` vim /etc/passwd ``` 找到创建的用户把 `/bin/bash` 修改为 `/sbin/nologin` 设置用户访问权限: ``` shell chown -R ftpuser /data/ftp ``` ### 6、 设置 vsftpd 服务开机启动 ``` shell systemctl enable vsftpd.service ```  ### 7、 启动暂停查看服务状态命令 ``` shell systemctl start vsftpd.service #启动 systemctl status vsftpd.service #查看状态 ```  ### 8、 常见问题 #### OOPS: could not read chroot() list file:/etc/vsftpd/chroot_list  这种情况是说明配置文件里面设置的chroot_list_file=_etc_vsftpd/chroot_list没找到这个文件 直接去_etc_vsftpd目录cp一个user_list或者把配置文件里面改名就行  #### OOPS: chroot  这种情况是selinux没有关闭,关闭selinux即可 ``` [root@localhost ~]# vim /etc/selinux/config SELINUX=disabled ``` #### 530 Login incorrect 网络上有好多解决方案,例如修改_etc_vsftpd.conf文件 将pam_service_name=vsftpd 修改为 pam_service_name=ftp ,虽然能够解决这个问题,但是这种方法其实是错误的。这样由于_etc_pam.d/ftp文件不存在,等于是绕过了PAM。 **vsftpd pam文件分析:** 1. _etc_pam.d/vsftpd 默认如下:  可能导致530错误的有 `auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed` 和 `auth required pam_shells.so` 2. _etc_ftpusers `auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed` 该配置项的含义是 _etc_ftpusers 中的用户禁止登陆,如果文件不存在在默认所有用户均允许登录. 所以确保用户没在这个文件内。 3. pam_shells.so `auth required pam_shells.so` 配置项的含义是:仅允许用户的登录shell为 _etc_shells文件内的shell命令时,才能登录。  而创建ftp用户时,为了禁止ssh登录,一般多为_bin_false 、_usr_sbin/nologin 等,显然不是一个有效的bash,也就无法登录了。 **解决方案:** 1. 查看_etc_ftpusers ,确保账号没有在这个文件内 2. 修改_etc_pam.d/vsftpd 将 `auth required pam_shells.so` 修改为-> `auth required pam_nologin.so` 或者将 `auth required pam_shells.so注释` 3. 重启vsftpd `systemctl restart vsftpd.service` ## 三、使用 supervisor 守护web程序进程 ### 1、安装 supervisor 并启动 ```shell yum install -y supervisor ``` 查看 supervisor 是否安装成功 ```shell supervisord --version ``` 启动 supervisor ```shell supervisord -c /etc/supervisord.conf ``` 查看 supervisor 是否启动成功 ```shell ps -ef|grep supervisord ```  设置 supervisor 为开机启动 ``` shell systemctl enable supervisord ``` 检查 supervisor 是否开机启动 ``` shell systemctl is-enabled supervisord ```  启动服务 ``` shell systemctl start supervisord ``` 查看启动状态 ``` shell systemctl status supervisord.service ```  ### 配置 supervisor supervisor 默认配置文件,放在 _etc_supervisord.conf 路径中: ``` [inet_http_server] ; #HTTP 服务器,提供 web 管理界面 port=*:9001 ; #Web 管理后台运行的 IP 和端口 username=user ; #登录管理后台的用户名 password=1234 ; #登录管理后台的密码 ``` 加上这一段 ``` [include] files = supervisord.d/*.ini ; #配置web配置文件夹 ``` 修改完之后重启:  ### 配置 supervisor 管理 web配置信息 创建一个.ini文件,放在目录supervisord.d下 ``` [program:demo] ; #程序名称 command=dotnet demo.dll ; #运行命令 directory=/web/publish; #目录 environment=ASPNETCORE_ENVIRONMENT=Production; #环境变量 user=root; #用户 stopsignal=INT; autostart=true; #如果是true的话,子进程将在supervisord启动后被自动启动 autorestart=true; #进程死掉后自动重启的情况 stderr_logfile=/var/log/demo/demo.err.log; #错误日志文件 stdout_logfile=/var/log/demo/demo.out.log; #输出日志文件 ``` ### 重启 supervisor ``` systemctl restart supervisord ``` 查看是否生效 ```shell supervisorctl status ```  ### 访问 然后通过http://ip:9001/ 访问web界面,账户名密码就是你配置的,效果如下:  ### supervisorctl 常用命令 查看任务状态:supervisorctl status 启动任务:supervisorctl start <name> 停止任务:supervisorctl stop <name> 重启任务:supervisorctl restart <name> 清除日志文件:supervisorctl clear <name> 清除多个日志文件:supervisorctl clear <name> <name> 清除所有日志文件:supervisorctl clear all 移除任务:supervisorctl remove <name> ### 常见问题 #### 启动时可能回报错:Another program is already listening on a port that one of our HTTP servers is config...rvisord.  * 解决方案一: 执行命令 find / -name supervisor.sock 然后 unlink _路径_supervisor.sock 最后再执行启动命令 systemctl start supervisord * 解决方案二: ``` ps -ef | grep supervisord #查看进程PID ``` 查看进程PID ``` root 2503 1 0 Nov19 ? 00:03:23 /usr/bin/python /usr/bin/supervisord root 21337 2556 0 18:15 pts/8 00:00:00 grep --color=auto supervisord ``` ``` kill -s SIGTERM 2503 #杀死进程 ``` ## 参考地址 1. 更多详细的vsftpd的配置说明:[https://baike.baidu.com/item/vsftpd/5254770?fr=aladdin](https://baike.baidu.com/item/vsftpd/5254770?fr=aladdin#3) 2. [Centos7安装搭建FTP服务器(最简便方法)](https://www.cnblogs.com/Sungeek/p/10148656.html) 3. [vsftpd 530 Login incorrect 根本原因和解决方案_wqh0830的博客-CSDN博客](https://blog.csdn.net/wqh0830/article/details/87795709) 4. [.Net Core 项目发布到Linux - CentOS 7(二)用Supervisor守护netcore进程 - tenghao510 - 博客园](https://www.cnblogs.com/tenghao510/p/11997125.html) 5. [.net core 使用代理服务器nginx 获取IP或者URL问题(.net core 怎么获取客户端ip,怎么获取nginx ip)_baidu_26504655的博客-CSDN博客](https://blog.csdn.net/baidu_26504655/article/details/91431583) 6. [nginx 域名绑定 域名, nginx 域名绑定 端口 - 云+社区 - 腾讯云](https://cloud.tencent.com/developer/article/1054418)