我把 C++ Mini Shell 做成了一个 Web Playground(Next.js × Unix System Calls)

0 阅读3分钟

最开始,这只是一个很典型的 C++ 系统项目:实现一个 Unix 风格 Mini Shell。

它支持:

  • 内建命令 cdexit
  • 外部命令执行
  • 输入输出重定向 < >
  • 单管道 |
  • 基于 fork + execvp + waitpid + dup2 + pipe 的核心 Unix 系统调用

但我很快发现一个问题:

这类系统项目虽然底层很扎实,但展示成本很高,往往只能在终端里演示。

对于 GitHub、作品集、技术文章,甚至实习面试来说,传播效率并不高

于是我做了一次非常有意思的工程化升级:

给我的 C++ Mini Shell 接了一个 Next.js Web Playground。

现在它不只是一个终端里的 shell,而是可以直接在浏览器里交互执行命令。

522bd0d36e188ab9f64b1b44d63bcee9.png image.png


一、Mini Shell 的底层核心

最初的 Shell Core 采用了比较标准的 Unix 进程控制方案。

整体模块拆分如下:

src/
├── main.cpp
├── parser.cpp
├── executor.cpp
└── pipe_executor.cpp

其中:

  • parser.cpp:负责 token 解析
  • executor.cpp:处理普通命令和重定向
  • pipe_executor.cpp:处理单管道
  • main.cpp:shell loop 和内建命令

核心能力包括:

1)外部命令执行

通过:

fork();
execvp();
waitpid();

完成父子进程模型。

2)输入输出重定向

通过:

dup2();
open();

将文件描述符重定向到标准输入输出。

3)单管道

通过:

pipe();
fork();
dup2();

实现:

echo hello | wc -c

这种经典链路。


二、为什么继续做 Web Playground

做到这里,它已经是一个完整的 Unix Mini Shell 了。

但我一直觉得:

好的系统项目,不应该只停留在终端里。

传统终端 demo 有几个问题:

  1. 展示成本高
  2. 面试时不方便快速演示
  3. GitHub 首页缺少交互感
  4. 不利于形成完整作品集闭环

所以我决定给它做一个浏览器展示层。

目标很明确:

让别人打开网页,就能直接体验我的 C++ shell。


三、核心升级:Next.js 调用 C++ 可执行文件

最终我采用的是:

Next.js API Route + Node.js spawn + C++ mini_shell

执行链路如下:

Web UI (Next.js)
   ↓
API Route (/api/execute)
   ↓
spawn ./mini_shell
   ↓
C++ parser / executor / pipe executor
   ↓
stdout / stderr
   ↓
Browser terminal panel

image.png

这里最核心的代码是:

const child = spawn("./mini_shell", [], {
  cwd: "/home/niki/mini-shell",
  stdio: "pipe",
});

然后把浏览器输入的命令写入 shell:

child.stdin.write(`${command}\n`);
child.stdin.write("exit\n");
child.stdin.end();

这样浏览器输入的每条命令,都会真正经过:

我自己写的 C++ shell 内核

而不是系统默认 shell。

这是整个项目最值钱的一步升级。


四、前端终端体验优化

只是能跑还不够,我继续把它做得更像一个真实终端。

前端基于 Next.js + React,实现了几个体验优化:

1)命令历史记录

每次执行后自动追加:

$ command
stdout
stderr

2)自动滚动到底部

每次执行新命令后自动滚动,体验更像 terminal。

3)空输出处理

像:

echo hello > out.txt

这种正常无输出命令,会显示:

(no output)

4)错误输出高亮

最满意的一点是把:

stderr

单独渲染成红色。

比如:

not_a_command

和:

cat not_exist.txt

都会在前端高亮显示。

0a434bc0ca5d905914913b7e232818f4.png

这一步之后,整个项目的“产品感”明显上来了。


五、实际效果演示

现在浏览器里已经可以直接跑完整链路。

基础命令

ls
pwd
echo hello
cat README.md

009265a567d2737416edea81e510b611.png


文件读取

cat README.md

87d0cd4798e171311aaab4161a00445b.png

重定向 + 管道

echo hello > out.txt
cat < out.txt
echo hello | wc -c

0a434bc0ca5d905914913b7e232818f4.png


错误处理

not_a_command
cat not_exist.txt

0a434bc0ca5d905914913b7e232818f4.png


六、我对这次升级最大的感受

这次做完之后,我最大的感受是:

很多系统项目不是不够强,而是缺一个更好的展示层。

Mini Shell 本身已经是一个很经典的 Unix 系统项目。

但当它被升级成:

浏览器可交互 Web Playground

之后,它的价值一下子就变成了:

  • GitHub 首页展示
  • 技术博客传播
  • 面试现场 demo
  • 作品集核心项目
  • 系统方向实习背书

它不再只是一个课程作业,而是一个:

可以被直接体验的工程作品。


七、下一步计划

下一步我准备继续往更像真实 shell 的方向升级:

  • 多级管道 cmd1 | cmd2 | cmd3
  • 持久 session shell
  • background job &
  • command history
  • WebSocket 长连接 shell
  • 更完整的 parser

继续把它往:

系统编程 × Full Stack Demo

这个方向推。


如果你也在做系统方向项目,我非常建议试试这种思路:

底层核心 + 展示层工程化

很多时候,项目差距不在“会不会写”,而在:

能不能让别人一眼看懂它的价值。