当前位置: 首页 > 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.gsyq.cn/news/1499137.html

相关文章:

  • 硬核干货|固态激光退火系统行业分析报告:IGZO/OLED 适配,上下游壁垒梳理
  • 如何拯救损坏的MP4视频:免费开源工具Untrunc的完整指南
  • 辞职在家挖漏洞?别急,听我说完
  • 固体饮料代加工找哪家?看懂厂家实力与服务再合作不踩坑
  • AI恶魔之眼产品使用说明
  • 药店进销存管理系统源码(ThinkPHP+MySQL),含后台管理、库存预警与过期提醒功能
  • Altium Designer 2024 原理图高级功能:层次式原理图实战精讲+全网最全避坑指南
  • 2026年6月行业内评价高的水果包装盒生产厂家推荐,中空板箱/水果周转箱/物流运输箱,水果包装盒公司推荐 - 品牌推荐师
  • HTTrack:将整个互联网装进口袋,离线浏览的革命性工具
  • 2026年6月净化工程厂商推荐,洁净工作台/快速卷帘门/净化工作台/净化工程/货淋室/洁净棚,净化工程厂商口碑推荐 - 品牌推荐师
  • 2026汕头防水补漏哪家靠谱?正规公司排名及避坑价格指南 - 苏易修缮
  • 网络安全从0到精通保姆级学习路线
  • 企业如何用Claude Code 或小龙虾发送 WhatsApp 消息?保姆级教程
  • AI推荐逻辑拆解:信息红、内容绿、信任蓝
  • TikTok评论批量采集神器:3分钟获取完整评论数据,无需编程基础
  • 案例分享:一个工牌如何帮品牌精准抓住客户心声,优化产品策略?
  • 2026美国留学中介挑选指南:新手入门必看 - 品牌2026
  • 5步打造专属宝可梦世界:pk3DS编辑器完全指南
  • 开源Qobuz无损音乐下载工具:构建您的个人高解析度音乐库
  • 3DS宝可梦ROM编辑器与随机化工具:打造独一无二的宝可梦冒险体验
  • 2026年腾讯云OpenClaw/Hermes Agent配置Token Plan部署流程来了
  • 2026年6月最新|电动葫芦品牌口碑推荐哪家好:按行业场景精准推荐,不踩坑 - 商业新知
  • 常州汽车音响改装哪家服务好?常州音乐人生同城无损改装避坑 - 音乐人生汽车音响
  • 2025年中国太阳能路灯行业十大品牌推荐榜单:技术实力与市场口碑深度解析
  • 沈阳灵活用工平台排行:5家头部机构合规能力实测对比 比较好的 口碑好的 2026年最新 - 起跑123
  • 绘本机有必要买吗?用了奇多多,彻底告别每晚陪读模式 - 新闻快传
  • 2026南京宝格丽首饰回收避坑指南:行情解析与正规机构甄选 - 开心测评
  • 2026花都区少儿武术培训怎么选?真实评价,学习力培养 - 17329971652
  • 2026重庆翡翠回收实力排名:本地实测6大正规平台,靠谱变现首选指南 - 薛定谔的梨花猫
  • LeetCode 380:Insert Delete GetRandom O(1) 题解和一些延伸