尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Jexus实战:老ASP.NET项目Linux部署与排障全记录

发布时间:2026/9/29 15:44:11

资讯中心
01
ARTICLE

Jexus实战:老ASP.NET项目Linux部署与排障全记录

Jexus实战:老ASP.NET项目Linux部署与排障全记录
我们做运维和全栈的估计都有过这种时刻手里压着一个老 ASP.NET 项目客户预算只给了 Linux 服务器Windows Server 授权费不给批项目代码又是 WebForms 或者老 MVC别说容器化连 .NET Framework 版本都定死在上去。我第一次遇到这个场景时第一反应是装 Apache 配 mod_mono结果把自己坑惨了。后来换成了 Jexus才算找到一套能踏实把 ASP.NET 应用跑在 Linux 上的方案。这篇就把我的部署经验、站点配置写法、反代用法和排障笔记一次说清楚。Jexus 是什么先说结论它是一个跑在 Linux 上的 Web 服务器最大的本事是直接对接 Mono 运行时让.aspx、.ashx、.asmx这类老 .NET 应用在 Linux 上像在 IIS 里一样跑。同时它也能当静态服务器、反向代理用不少人在上面跑 ASP.NET Core 的 Kestrel 进程。它适合三类人手里有老 .NET 项目必须迁到 Linux 的开发、不想给内网小业务买 Windows 授权的运维以及想找一个比 nginx 更“懂 .NET”的轻量入口的爱好者。1. 先搞明白Jexus 到底解决了一个什么问题1.1 老 .NET 应用跑 Linux 的三条路为什么最后选了它当年摆在我面前的无非三条路第一个是 Apache 或 nginx 加 mod_mono让外部请求通过 FastCGI 转给 Mono 处理第二个是直接把应用改成 ASP.NET Core重写一遍第三个就是用 Jexus。第一条路我实际踩过配置不复杂但稳定性一言难尽。mod_mono 对长连接、并发高一点的场景处理很勉强应用一崩整个 worker 都要跟着重启日志还不直观。第二个方案对老项目来说成本太高很多业务逻辑和第三方控件根本没法平滑迁移。Jexus 出现之后等于有人把“IIS 在 Linux 上的替代品”这件事专门做了一遍它不是一个通用 Web 服务器顺带支持 .NET而是从设计上就以托管 .NET 应用为核心目标。我后来给团队讲为什么选它用的类比是nginx 像一把万能瑞士军刀切什么都行但你要给它配一个专门的模块才能切豆腐Jexus 更像一把专门切豆腐的刀你只做 .NET 这桌菜的时候它就是比通用方案顺手。1.2 Jexus 和 IIS、nginx、Kestrel 的真实分工很多人第一次听到 Jexus 会问我有 Kestrel 了还要它干嘛这里要分两类情况经典 ASP.NET.NET Framework 4.x 时代的 WebForms / MVC 5 等Kestrel 根本不认识它Jexus 是少数能直接把这类应用“宿主”在 Linux 上的选择之一。ASP.NET Core现代 .NETKestrel 自己是 Web 服务器但生产环境通常需要一个前置服务器处理 80/443、静态文件、日志和进程守护Jexus 可以扮演这个前置角色类似 nginx 的用途。我用一张表对比过它们的分工至今觉得这个对比最适合给团队新人看组件擅长弱点和 Jexus 的关系IISWindows 下完整托管 .NET图形管理方便只认 Windows授权成本高Linux 下事实上的替代目标nginx静态文件、反代、负载均衡生态巨大不能直接跑经典 ASP.NET可共存Jexus 也可替代其反代角色KestrelASP.NET Core 自带的跨平台服务器裸奔上生产要处理端口、静态文件、守护常作为 Jexus 反代的上游JexusLinux 下直接托管 Mono/.NET反代配置简单生态小、版本更新慢、文档碎片化本文主角这个对比想说明一件事Jexus 的核心价值不在“性能指标比 nginx 高多少”而在于“这活儿只有它干得最顺”。2. 部署前的地基Mono 环境和 Jexus 安装2.1 Mono 版本选型和安装的坑Jexus 虽然自带 ASP.NET 宿主但它不包含 .NET 运行时所以安装 Jexus 之前必须先把 Mono 装好。Mono 版本直接影响 Jexus 的稳定性我自己的经验是 Jexus 6.x 搭配 Mono 5.x 以上最稳低于 4.x 会出现各种怪异的 500 错误和程序集加载失败。这里有一个常见的安装误区直接用系统源装 mono。CentOS 7 默认源里的 mono 版本极度落后Ubuntu 18.04 的源里版本也很保守。如果你急着部署装完很可能发现某些代码编译时没问题、运行时却报方法不存在。我当时的做法是# Ubuntu / Debian 系先加 mono 官方源别用系统源里的老版本 sudo apt install gnupg ca-certificates sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF echo deb https://download.mono-project.com/repo/ubuntu stable-bionic main | sudo tee /etc/apt/sources.list.d/mono-official-stable.list sudo apt update sudo apt install mono-complete # CentOS / RHEL 系如果只有老源建议直接编译较新版本或者用官方构建包装完之后别急着下一步先验证一下mono -V至少能看到对应版本的编译时间如果版本号明显老旧后面 Jexus 报的错会让你根本联想不到是 Mono 的问题。2.2 Jexus 安装与目录结构Jexus 的安装包是一个 tar.gz没有复杂的依赖解压执行 install 脚本就行。64 位 Linux 上用 6.2 这个版本居多32 位老机器才需要去翻 5.x 的老包。tar -zxvf jexus-6.2-x64.tar.gz cd jexus-6.2-x64 sudo ./install.sh默认安装目录是/usr/jexus里面最核心的东西就两个jws是主程序siteconf是站点配置目录。安装脚本会自动注册服务但我不太推荐依赖服务管理直接使用 jws 命令反而更直观sudo /usr/jexus/jws start sudo /usr/jexus/jws restart sudo /usr/jexus/jws status sudo /usr/jexus/jws testtest这个命令很多新手不知道它用来检查站点配置有没有语法错误改完配置以后先 test 再 restart能少走很多弯路。2.3 安装后的自检装完不是马上创建站点先确认默认配置能起来。我第一次装完就直接去改配置结果分不清是自己写错了还是环境有问题后来养成一个习惯先启动默认站点能访问到 Jexus 默认页再动手改。curl -I http://127.0.0.1/如果返回 200 或者看到响应头里有 Jexus 标识说明基础环境通了。如果连这一步都不通优先检查 80 端口是否被占用、防火墙是否拦截别急着怀疑 Jexus。3. 站点配置拆解从零写一个能跑起来的 siteconf3.1 最小可用配置逐行解释Jexus 的站点配置是一个纯文本文件默认放在/usr/jexus/siteconf/default一行一个指令。我见过不少第一次用的人被 root 指令的写法难住这里展开讲清楚。port80 root/ /var/www/myapp hostswww.myapp.com,myapp.com indexindex.aspx,index.html log/var/log/jexus/myapp.logport80站点监听端口这是必须项。root/ /var/www/myapp注意这里的写法/和实际路径之间有一个空格。这个/表示站点根路径映射到后面的物理目录。如果你直接写成root/var/www/myapp配置解析会失败或者行为异常。这是我第一次配置时踩的最大坑后来看官方文档才发现空格是有讲究的。hostswww.myapp.com,myapp.com绑定域名多个域名用逗号分隔。生产环境里一个端口跑多个站点就靠它区分如果只有一个站点想匹配所有 Host可以写hosts*。indexindex.aspx,index.html默认首页顺序Jexus 会从左到右找存在的文件。log/var/log/jexus/myapp.log站点访问日志路径建议每个站点单独一个文件后面排查问题会舒服很多。3.2 虚拟目录和多站点同端口虚拟目录是老 .NET 应用里很常见的需求比如文件存储在一个独立磁盘路径但应用要通过 URL 子路径访问。Jexus 里用vdir指令做映射vdir/upload /data/files含义是把 URL 里的/upload映射到物理路径/data/files。注意它和 root 一样路径之间要空格我习惯把虚拟目录段放在前面物理路径放后面这样和 root 语法的直觉一致。多站点同端口则是靠 hosts 区别的比如# 站点 A 配置 port80 root/ /var/www/sitea hostssitea.com # 站点 B 配置 port80 root/ /var/www/siteb hostssiteb.com每个配置文件放在siteconf目录下文件名就是站点名重启后 Jexus 根据请求的 Host 头分发。这里有个隐藏坑当你配置了hosts*的默认站点时它能“吃掉”所有未匹配的域名请求所以生产上不要把写死域名的站点和 hosts* 的站点混在同一个端口不然调半天都搞不清请求去了哪。3.3 hosts、日志那些容易忽略的细节hosts 匹配是严格基于 Host 头的不带端口、不带路径。如果你直接用 IP 访问一个只有域名绑定的站点会落到默认站点或者直接访问不了。调试阶段如果不想搞域名解析可以临时把 hosts 改成*确认业务正常后再改回具体域名。日志方面Jexus 默认日志输出位置不一定是你想要的我建议每个站点都显式指定 log 路径。另外定期清理日志很重要我见过一台跑了两年的机器日志文件占了几十个 GB查问题的时候连 grep 都卡。配合 logrotate 或者一个简单的 crontab 清理脚本就能解决。4. 实战把 ASP.NET MVC 老项目搬到 Jexus4.1 发布产物和 DLL 依赖的坑部署经典 ASP.NET 项目和发布 .NET Core 项目完全是两个逻辑。老项目的发布产物不是单个 exe而是一堆文件包括bin目录下的所有 DLL、Views里的模板、Content/Scripts里的静态资源。我的操作流程是在 Windows 上用 Visual Studio 执行 Release 发布。把整个发布目录打包上传到服务器的/var/www/myapp。确保bin目录原样保留包括那些你以为是“系统自带”的程序集。这里最容易翻车的是第三方 DLL。很多老项目依赖的某些组件在 Mono 下没有完全对应实现运行时才发现缺程序集。我的建议是先在开发机确认项目没有依赖 Windows 专属的 DLL再上服务器。真遇上了优先找这个库有没有跨平台版本没有的话只能考虑替换实现这一步没办法完全自动化。4.2 数据库连接字符串和 Linux 区分大小写老 ASP.NET 项目普遍连 SQL Server连接字符串里常写Integrated SecurityTrue这在 Windows 上是本机身份验证到了 Linux 上直接废掉。必须改成账号密码模式connectionStrings add nameMainDB connectionStringServer192.168.1.10;DatabaseMyAppDB;User IDsa;Password****** providerNameSystem.Data.SqlClient / /connectionStrings另外一个隐蔽问题是大小写敏感。Linux 文件系统对大小写敏感但很多从 Windows 搬过来的项目默认不敏感。数据库名写错大小写、配置里引用的路径大小写对不上都是我在 Jexus 部署里排过的实际故障。打包前建议全局搜索一下文件路径引用统一规范。4.3 文件权限和 web.config 差异权限问题排在故障榜前列。Jexus 默认以 root 身份启动但这不代表你的应用就拥有全部权限尤其涉及上传目录、日志目录时。我习惯给应用根目录设置合理的属主和权限sudo chown -R www-data:www-data /var/www/myapp sudo find /var/www/myapp -type d -exec chmod 775 {} \; sudo find /var/www/myapp -type f -exec chmod 664 {} \;web.config 在 Mono 下的解析和 IIS 有差异。system.webServer里 IIS 专属的配置节在 Mono 里可能不被识别我遇到过因为留着modules配置导致整个应用 500 的情况。经验是先删掉所有system.webServer下的非必要配置跑通了再加回。customErrors、httpRuntime这些基础配置 Mono 都支持不用太担心。5. 反代和 ASP.NET Core让 Jexus 当一个轻量入口5.1 反向代理配置示例Jexus 到今天还被大量使用另一个原因就是它可以顶替 nginx 做反向代理。我自己最常用的是这个场景一台服务器上跑 ASP.NET Core 应用Kestrel 监听内网 5000 端口Jexus 监听 80 对外提供访问。port80 root/ /var/www/static hostsmyapp.com proxy127.0.0.1:5000这样外部用户只接触 80 端口Kestrel 不用直接暴露。注意 root 和 proxy 同时存在时Jexus 会优先处理静态文件请求其余动态请求转发给上游。如果不想要静态文件逻辑root 指向一个几乎为空的目录也行。我第一次就把 root 写成了 web 应用目录导致 Jexus 试图直接返回静态文件而不是转发排查了好久才发现是两者优先级理解错了。对应的 Kestrel 侧我建议监听 127.0.0.1 而不是 0.0.0.0这样内网其他机器也无法绕过 Jexus 直接访问安全性好很多。5.2 多上游和 HTTPS 终结的简单方案反代场景再深入一点就是负载均衡。Jexus 支持把同一个站点配置里的 proxy 指到多个上游地址相当于一个极简负载均衡器。我在测试环境这么写过proxy192.168.1.11:5000,192.168.1.12:5000具体轮询策略不同版本可能略有差异生产环境我其实更推荐用 nginx 做复杂均衡但内网小规模场景 Jexus 够用且省事。HTTPS 方面如果只是给反代加一层加密我更推荐把证书放在 Jexus 这一层处理因为终止 TLS 之后内网到 Kestrel 的流量还是明文省了不少证书配置的工作量。Jexus 老版本与新版之间证书配置的指令格式有差异部署的时候一定以你安装版本的官方文档为准不要照抄网上老帖子的命令。6. 这几年排障攒下来的速查表6.1 启动类故障症状原因处理jws status显示未运行端口被占用通常是 nginx、Apache 或其他站点netstat -tlnp查看端口占用改 port 或停冲突服务配置改了但没生效修改后没重启或 test 报错每次改 siteconf 先jws test再jws restart服务起一下就崩Mono 版本过老或程序集不兼容升级 Mono检查应用日志默认页能开自己站点不行hosts 配置和访问域名不匹配临时改hosts*验证业务再改回域名6.2 访问类故障症状原因处理访问.aspx直接变成下载Mono 或 Jexus 的 ASP.NET 处理进程没起来确认 Mono 安装完整mono -V看版本重启 Jexus页面 503应用池进程崩溃或目录权限错看站点日志检查站点根目录和 bin 权限页面 500web.config 配置节不兼容、程序集缺失临时去 IIS 专属配置节查看 Jexus 日志里的异常堆栈静态图片 404root 路径与文件实际位置大小写不符核对路径大小写反代后 502/504上游 Kestrel 没启动或内网端口被防火墙挡先在服务器上curl 127.0.0.1:5000验证上游6.3 独门经验不是文档里会写的第一个经验站点配置文件改之前先拷贝一份带日期的备份。Jexus 的 siteconf 没有语法高亮一个空格位置错了要人肉看很久备份能让你十秒回滚。第二个经验日志必须单独分目录并且做切割。我在生产服务器上习惯建/var/log/jexus/统一放按站点分文件配合 crontab 每月压缩一次。这样遇到问题grep 一个文件就能还原整个时间线。第三个经验也是我想强调的遇到 500 不要只盯着应用代码。在 Jexus 环境里绝大多数 500 的根源是 Mono 版本和程序集加载问题先把mono -V确认了再去看 web.config最后才怀疑业务代码。这个排查顺序帮我省了很多时间。7. 我的最终建议与选择心法最后分享一点个人判断。Jexus 在今天算不上热点技术新项目我不会推荐它新一代跨平台开发直接上 ASP.NET Core 加 nginx 是更主流的选择社区活跃度和工具链都更健全。但如果你和我一样每周都在和老系统打交道面对的是一堆没法重写的 ASP.NET 代码Jexus 依然是一个值得保留在工具箱里的方案。它的学习成本真的很低我一个下午就完成了从零到能跑这对紧急救火场景太重要了。实际用到现在我体会最深的是“匹配”二字。不要因为某个技术在社区里讨论少就一票否决如果你的真实场景是 Linux 上的老 .NET 应用Jexus 就是一个切得动这块豆腐的专用刀。而如果你的场景是全新的 .NET Core 服务那就别硬套 Jexus直接 nginx 加 Kestrel 反而更干净。这类工具我还有最后一个习惯要分享每台部署了 Jexus 的服务器上我都会留一个最简单的测试站点占着 8080 端口专门用来验证 Jexus 本身是否健康。生产系统出问题时先访问这个测试站点就能快速区分是 Jexus 的问题还是业务应用的问题。这个不起眼的动作这几年帮我躲过了至少四五次无头苍蝇式的排查。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。