当前位置: 首页 > news >正文

我给工具站加了一个在线代码运行器,结果先被 Docker 沙盒教育了一遍

最近给自己的工具站加了一个在线代码运行功能。
地址: https://web.fushengtool.com/dev/code_runner
最开始只是想补一个小能力:用户在页面里输入一段代码,选择语言,点击运行,然后页面返回执行结果。

我原本以为这只是一个很简单的后端接口。真正做起来以后才发现,这个功能和普通的文本处理工具不太一样。

像 JSON 格式化、时间戳转换、Base64 编解码这类工具,大部分逻辑都可以在浏览器里完成。用户输入文本,前端处理后直接展示结果即可。

但在线代码运行器不一样。它需要准备运行环境,还要处理不同语言的执行方式、运行超时、错误输出、结果截断等问题。

这篇文章记录一下我这次实现 Code Runner 的过程。

一、为什么想做这个功能

我平时写代码时,经常会遇到一些很小的验证场景。

比如:

  • 临时写几行 Python,验证一个字符串处理结果;
  • 看一段 JavaScript 示例,想快速跑一下输出;
  • 写正则或时间处理逻辑,想确认边界情况;
  • 写一个小算法,不想专门打开 IDE;
  • 看别人给的示例代码,想马上试一下。

这些需求都不大,但出现频率不低。

如果每次都打开编辑器、新建文件、配置环境,会有点麻烦。所以我就想在工具站里加一个轻量的在线代码运行功能。

第一版先支持 Python,后面再逐步扩展到 JavaScript、Go、Java、C、C++ 等语言。

二、整体设计

整体流程大概分成三层。

前端页面 ↓ 后端接口 ↓ 代码运行模块

前端页面负责:

  • 选择编程语言;
  • 编辑代码;
  • 点击运行;
  • 展示运行结果;
  • 展示错误信息和耗时。

后端接口负责:

  • 校验参数;
  • 判断语言是否支持;
  • 调用对应语言的运行逻辑;
  • 返回统一格式的结果。

代码运行模块负责:

  • 准备代码文件;
  • 执行对应命令;
  • 收集标准输出;
  • 收集错误输出;
  • 控制运行时间;
  • 处理异常情况。

拆成这几层以后,前端和后端都比较清楚。前端不用关心每种语言怎么运行,后端也可以把不同语言的差异收敛到配置里。

三、先从 Python 开始

Python 是最适合做第一版的语言。

它不需要编译,写入文件后直接执行即可。

比如用户输入:

print("hello world")

后端只需要把代码保存成临时文件,然后执行:

python main.py

再把输出结果返回给前端。

第一版做完 Python 后,整个流程基本就跑通了:

输入代码 → 提交接口 → 执行代码 → 获取输出 → 返回页面

这个阶段主要解决的是接口结构和返回格式。

我最后返回的数据大概包括:

  • 是否成功;
  • 标准输出;
  • 错误输出;
  • 退出码;
  • 是否超时;
  • 运行耗时。

这样前端展示时会比较灵活。

四、扩展到 JavaScript

JavaScript 的处理方式和 Python 类似。

用户代码保存成文件后,使用 Node.js 执行:

nodemain.js

这一类解释型语言的接入成本相对较低。

主要要处理的是:

  • 运行环境是否存在;
  • 错误输出如何展示;
  • 执行时间如何限制;
  • 输出太长时如何截断。

做到这里时,我发现如果后面还要继续加语言,不能每种语言都写一大段独立逻辑。否则代码会越来越散。

所以我开始把语言配置抽象出来。

五、把语言差异整理成配置

不同语言真正不同的地方,主要是这些:

  • 代码文件名;
  • 是否需要编译;
  • 编译命令;
  • 运行命令;
  • 默认超时时间;
  • 输出长度限制。

所以可以把每种语言整理成类似这样的配置:

语言:Python 文件名:main.py 运行命令:python main.py 是否需要编译:否
语言:JavaScript 文件名:main.js 运行命令:node main.js 是否需要编译:否
语言:C 文件名:main.c 编译命令:gcc main.c -o main 运行命令:./main 是否需要编译:是

这样后面新增语言时,思路会清楚很多。

不是在业务逻辑里不断加判断,而是新增一份语言配置。

六、编译型语言的处理

支持 C、C++、Java、Go 之后,流程会比 Python 和 JavaScript 多一步。

比如 C 语言:

gcc main.c-omain ./main

Java:

javac Main.javajavaMain

Go:

go run main.go

这些语言需要注意几个问题。

第一,编译错误和运行错误要分开。

编译阶段失败,就不应该继续执行运行命令。比如 C 语言少了分号,编译阶段就会报错,这时候直接把编译错误返回给用户即可。

第二,不同语言的错误格式不一样。

Python 的 Traceback、Java 的 Exception、GCC 的编译错误、Node.js 的异常提示,看起来都不一样。前端展示时不能强行格式化,只要把原始错误清楚展示出来就可以。

第三,运行时间要有限制。

用户可能写出死循环,也可能代码本身执行比较慢。接口不能一直等待,所以需要设置超时时间。

第四,输出长度要有限制。

如果用户代码输出大量内容,接口和页面都会受到影响。所以需要对 stdout 和 stderr 做最大长度限制。

七、统一返回格式

为了让前端处理简单,我把所有语言的结果都统一成一套格式。

比如:

{"success":true,"stdout":"hello world","stderr":"","exit_code":0,"timeout":false,"duration_ms":120}

如果运行失败,也使用同样的结构:

{"success":false,"stdout":"","stderr":"SyntaxError: ...","exit_code":1,"timeout":false,"duration_ms":80}

这样前端不用针对每种语言写一套展示逻辑。

成功就展示输出,失败就展示错误。超时就给出超时提示。

八、前端体验

前端页面我主要关注几个点。

第一,打开页面要能直接试。

每种语言最好有默认示例代码。用户不用自己先想写什么,打开就能点运行。

第二,输出区域要清楚。

标准输出和错误输出最好分开展示。否则用户分不清到底是代码正常输出,还是运行错误。

第三,按钮状态要明确。

运行中要禁用按钮,避免用户连续点击提交多个请求。

第四,错误提示不要太笼统。

如果是代码报错,就展示代码错误。如果是接口异常,就展示接口异常。不要所有情况都只提示“运行失败”。

九、这次做完后的感受

做这个功能之前,我以为重点是“怎么把代码跑起来”。

做完以后,我觉得重点其实是“怎么把结果稳定地返回给用户”。

因为代码运行本身只是其中一步,前后还要处理很多细节:

  • 参数校验;
  • 临时文件管理;
  • 多语言配置;
  • 编译和运行流程;
  • 超时控制;
  • 输出截断;
  • 错误展示;
  • 前端状态管理。

这些细节都不算特别难,但少一个就会影响体验。

十、后续计划

后面我准备继续优化几个方向。

  1. 增加更多示例

给每种语言准备一些常见示例,比如字符串处理、数组遍历、时间格式化等。

  1. 优化错误提示

常见错误可以做一些简单说明,让用户更容易看懂。

  1. 支持运行历史

登录用户可以保存最近运行过的代码片段,下次继续编辑。

  1. 优化移动端体验

手机上写代码不一定方便,但查看和运行简单示例还是有需求。

  1. 逐步增加语言

先把常用语言跑稳定,再考虑更多语言,不急着一次性加太多。

十一、总结

在线代码运行器看起来是一个小功能,但实现时会遇到不少细节。

我的经验是:

  • 先从 Python 这类简单语言开始;
  • 返回格式一开始就统一;
  • 编译错误和运行错误分开处理;
  • 一定要设置超时时间;
  • 输出内容要做长度限制;
  • 前端要把 stdout 和 stderr 展示清楚;
  • 多语言最好用配置方式扩展。

如果你也想做类似功能,建议不要一上来就支持很多语言。

先把一两个语言的完整链路跑通,再逐步扩展。这样后面遇到问题时,排查会轻松很多。

http://www.jsqmd.com/news/987390/

相关文章:

  • macOS 上的 Ghostty 1.3.1 快捷键
  • 算法与高并发调优:从时间复杂度到系统吞吐量的全链路优化之道
  • 「权威评测」2026年国内五大中频炉厂家实力推荐,谁才是靠谱之选? - 品研笔录
  • 2026 上海周边云仓 TOP10 深度测评:海盛云仓领跑,全链路数字化仓配服务商推荐 - 玖叁鹿
  • 《你好!数学·最亲切的数学概念启蒙图画书》PDF+音频
  • 如何拯救损坏的MP4视频:免费开源工具Untrunc的完整指南
  • 云服务成本优化:从资源利用率到架构选型的成本收益分析
  • 辞职在家挖漏洞?别急,听我说完
  • 硬核干货|固态激光退火系统行业分析报告:IGZO/OLED 适配,上下游壁垒梳理
  • 2026年6月市场上头部静音卷帘门服务商怎么选择,车库门/高端透视卷帘门/铝包铜卷帘门,静音卷帘门服务商推荐 - 品牌推荐师
  • 3大创新技术突破:Dislocker如何实现BitLocker加密卷的跨平台无缝访问
  • 固体饮料代加工找哪家?看懂厂家实力与服务再合作不踩坑
  • OBS-VST插件终极指南:3步解决直播音质问题的完整教程
  • AI 全流程赋能:拓维海云天领跑智能数字化考评新生态,构建在线考试系统新标杆 - 玖叁鹿
  • AI恶魔之眼产品使用说明
  • Altium Designer 2024 原理图高级功能:层次式原理图实战精讲+全网最全避坑指南
  • 大数据处理全家桶:Hadoop 是什么?Spark、Flink 们都是啥关系?
  • 药店进销存管理系统源码(ThinkPHP+MySQL),含后台管理、库存预警与过期提醒功能
  • ISO系列认证体系详解:企业合规运营的基石
  • 2026年6月行业内评价高的水果包装盒生产厂家推荐,中空板箱/水果周转箱/物流运输箱,水果包装盒公司推荐 - 品牌推荐师
  • 深耕厨造三十载 以硬核实力定义水槽行业标准 - 玖叁鹿
  • 2026年6月最新|揭秘!嘉兴中央空调安装公司推荐哪家靠谱?老师傅教你识别正规军 - 商业新知
  • 星露谷物语模组开发新纪元:SMAPI如何彻底改变游戏扩展体验
  • 国内首个!Gitee Repo 制品管理系统通过可信云最高级评估,国产软件供应链安全再添利器
  • 青岛黄金回收平台综合实力排名及实地测评指南 - 薛定谔的梨花猫
  • Unity URP兼容的雪山雪地场景资源包:含地形预制体、PBR雪材质、环境预设与粒子效果
  • 2026年6月净化工程厂商推荐,洁净工作台/快速卷帘门/净化工作台/净化工程/货淋室/洁净棚,净化工程厂商口碑推荐 - 品牌推荐师
  • 互联网产品团队如何用原型工具进行用户测试与需求验证
  • 068、RGB 域降噪:RGB 空间的频域降噪、NLM 与小波降噪的工程实现
  • 2026汕头防水补漏哪家靠谱?正规公司排名及避坑价格指南 - 苏易修缮