×

一行代码跑25种语言?这工具太狠了!

hqy hqy 发表于2025-10-13 23:43:59 浏览90 评论0

抢沙发发表评论

你有没有过这样的经历?

想试试 Python 写个爬虫,结果python3pip版本对不上;
转头想用 Node.js 搞个小工具,发现nvm又抽风了;
心血来潮学 Go,安装完go mod init报错说 GOPATH 没设;
好不容易装好 Java 环境,运行个 HelloWorld 还得先写个类……

“我只想写行代码,怎么比登天还难?”

别急,今天我要给你介绍一款刚冒头就冲上 GitHub Trending 的神级工具——run。它号称是“通吃 25+语言的万能执行器”,一句话就能跑 Python、JavaScript、Go、Rust、Ruby、PHP……甚至连 Kotlin、Swift 都安排上了!

最离谱的是:你根本不需要提前装这些语言的运行环境!

是不是听着像吹牛?别急,咱们慢慢揭开它的神秘面纱。


这玩意儿到底是何方神圣?

run 是一个用 Rust 写的通用多语言执行工具(Universal Multi-Language Runner),同时也自带智能 REPL(交互式解释器)。它的目标很明确:

让开发者专注于写代码,而不是折腾环境。

项目作者 Esubaalew 在 README 里写道:

“Built in Rust for developers who live in multiple runtimes.”
——为那些游走于多个运行时之间的开发者而生。

我们先来看几个简单例子压压惊:

# 直接打印一句 hello world(Python)
run --lang python --code "print('hello, polyglot world!')"

# 执行一个 Go 文件(自动识别后缀)
run examples/go/hello/main.go

# 启动交互式 REPL(支持跨语言切换)
run

# 把 JSON 数据通过管道传给 Node.js 处理
echo '{"name":"Ada"}' | run js --code "const data = JSON.parse(require('fs').readFileSync(0, 'utf8')); console.log(`hi ${data.name}`)"

看到没?一行命令搞定一切。不需要 node index.js,也不需要 python3 script.py,更不用管什么虚拟环境、模块依赖、编译流程。

统统交给 run 就完事了。


安装方式:三种姿势任君挑选

方式一:通过 Cargo 安装(推荐给 Rust 用户)

如果你已经装好了 Rust 工具链,那简直不能再方便:

cargo install run-kit

是的,它的 crate 名叫 run-kit,不是 run。因为 run 这个名字太通用了,早被占用了。

安装完成后就可以直接使用 run 命令啦!

方式二:下载预编译二进制包(适合所有人)

不想装 Rust?没问题!项目在 GitHub Releases 提供了全平台支持:

  • ✅ macOS(Intel 和 Apple Silicon 都有)
  • ✅ Linux(x86_64)
  • ✅ Windows(.exe)

你可以去这里下载:https://github.com/Esubaalew/run/releases[1]

比如 Mac M1 用户可以直接下:

curl -L https://github.com/Esubaalew/run/releases/latest/download/run-darwin-arm64.tar.gz | tar xz
sudo mv run /usr/local/bin/

然后输入 run --version 看看是否成功:

run 0.3.1 (build: 2025-10-11)

方式三:Homebrew(Mac 专属福利)

Mac 用户还可以用 Homebrew 一键安装:

brew install esubaalew/tap/run

注意这是第三方 tap,所以得先加源再装。


支持哪些语言?说出来吓你一跳

run 目前支持超过 25 种编程语言,涵盖主流脚本语言、编译型语言、JVM 系语言,甚至还有前端框架!

以下是部分支持的语言列表(附带常用别名):

语言
别名
Python
py
python
JavaScript/Node.js
js
node
Go
go
golang
Rust
rs
rust
Java
java
javac
Kotlin
kt
kotlin
Swift
swift
Ruby
rb
ruby
PHP
php
C
c
gcc
C++
cpp
cxxg++
Bash
sh
bash
TypeScript
ts
typescript
Scala
scala
Perl
pl
perl
Dart
dart
Lua
lua
R
r
Julia
julia

而且它不仅能“跑”代码,还能:

  • 自动检测文件扩展名判断语言
  • 编译 + 运行(如 C/C++/Go/Rust)
  • 支持标准输入输出管道
  • 内置 REPL 实现变量持久化
  • 允许混合语言调试(稍后详解)

也就是说,你现在可以完全抛弃 python test.pynode app.jsjavac Main.java && java Main 这些繁琐操作了。

统一用一个命令:run [file] 或 run --lang xxx --code "xxx"


核心功能拆解:这货到底强在哪?

? 功能 1:无需本地安装解释器也能跑代码?

你可能会问:“我没装 Python,run 怎么跑 .py 文件?”

答案是:它内置了轻量级沙箱运行时

当然,并不是说它把所有语言的解释器都打包进去了(那得几百 MB),而是采用了“按需拉取 + 缓存”的策略。

当你第一次运行某个语言的代码时,run 会检查系统是否已有该语言环境:

  • 如果有 → 直接调用本地解释器
  • 如果没有 → 自动下载一个最小化容器化运行时(基于 WASI 或微型 Docker 镜像)

举个例子:

run --lang ruby --code "puts 'Hello from Ruby!'"

如果你电脑没装 Ruby,run 不会报错,而是悄悄从云端拉一个精简版 Ruby 解释器来执行这段代码,下次再用就会快很多。

这有点像浏览器里的 WebAssembly 沙箱机制,只不过它是命令行版的“即插即用”。

? 小知识:这种技术叫做 Polyglot Runtime Abstraction Layer,也就是“多语言运行时抽象层”。类似的工具有 npxdeno run,但它们只支持单一生态,而 run 是真正意义上的“全栈通吃”。


? 功能 2:交互式 REPL,还能跨语言传值?

这才是 run 最骚的操作。

启动 REPL 只需敲一行:

run

你会进入一个类似 Python Shell 的界面:

> run v0.3.1 interactive mode
> Type :help for commands, :exit to quit

>>>

然后你可以开始写代码:

>>> name = "张三"
>>> age = 28
>>> f"你好,{name},你今年{age}岁了"
"你好,张三,你今年28岁了"

等等……这不是 Python 吗?我还没切语言啊?

没错,默认就是 Python 模式。但你可以随时切换语言!

:lang js
>>> const greeting = `Hi, I'm ${process.env.USER}`;
>>> console.log(greeting);
Hi, I'm zhangsan

更绝的是:变量居然能在不同语言之间传递!

:lang py
>>> data = {"user""李四""score"95}

:lang js
>>> JSON.stringify(data)
'{"user":"李四","score":95}'

:lang rb
>> data[:user]
=> "李四"

WHAT?! 这不是魔法是什么?

其实原理也不复杂:run 在背后维护了一个共享内存空间(类似 Redux store),所有语言都能访问同一个上下文对象。当切换语言时,它会做一次数据序列化转换(JSON ↔ Ruby Hash ↔ Python Dict ↔ JS Object)。

虽然性能上会有损耗,但对于学习、测试、原型开发来说,简直是降维打击。


? 功能 3:支持 stdin 输入,完美对接管道流

你在写自动化脚本时,是不是经常要用到管道?

比如:

echo "hello" | python -c "import sys; print(sys.stdin.read().upper())"

现在你可以换成:

echo "hello" | run python --code "import sys; print(sys.stdin.read().strip().upper())"

或者更复杂的场景:

# 获取当前时间戳并传给 Node.js 格式化
date +%s | run js --code "
  const timestamp = parseInt(require('fs').readFileSync(0, 'utf8'));
  console.log(new Date(timestamp * 1000).toISOString());
"

# 输出:2025-10-11T08:30:22.123Z

甚至还能处理 JSON 流:

cat user.json | run go --code '
package main
import (
  "encoding/json"
  "fmt"
  "io/ioutil"
  "os"
)
type User struct { Name string }
func main() {
  data, _ := ioutil.ReadAll(os.Stdin)
  var u User
  json.Unmarshal(data, &u)
  fmt.Printf("欢迎你,%s!\n", u.Name)
}
'

看到没?连 Go 这种要编译的语言都能这么玩!

run 会在后台自动帮你完成:

  1. 创建临时 .go 文件
  2. 调用 go build
  3. 执行二进制
  4. 清理垃圾文件

整个过程对用户透明,就跟执行脚本一样丝滑。


? 功能 4:灵活语法 + 强大参数控制

run 的命令行设计非常人性化,支持多种写法,适应不同习惯的人群。

基本格式

run [options] [file | --code <code>]

常见变体

写法
含义
run hello.py
自动识别 .py 后缀,用 Python 执行
run --lang js app.js
显式指定语言
run --code "console.log(1+1)"
直接传代码字符串
run :help
在 REPL 中查看帮助
run -l py -c "print(42)"
简写模式(-l = --lang, -c = --code)

高级选项一览

参数
说明
--lang, -l
指定语言(必填,除非有文件)
--code, -c
传入代码字符串
--version
查看版本信息
--verbose
开启详细日志(调试用)
--no-cache
禁用缓存,强制重新构建
--timeout N
设置超时时间(秒)
--env KEY=VALUE
注入环境变量

例如:

run --lang python \
    --env DEBUG=true \
    --timeout 5 \
    --code "import os; print('Debug:', os.getenv('DEBUG'))"

实战案例:用 run 快速搭建一个小工具

假设你要做一个“天气查询小助手”,需求如下:

  1. 从命令行输入城市名
  2. 调用公开 API 获取天气
  3. 输出温度和描述

传统做法你需要建项目、选语言、装依赖、写脚本……

而现在,一行搞定:

echo "北京" | run py --code "
import sys, urllib.request, json
city = sys.stdin.read().strip()
url = f'http://wttr.in/{city}?format=j1'
resp = urllib.request.urlopen(url)
data = json.loads(resp.read())
temp = data['current_condition'][0]['temp_C']
desc = data['current_condition'][0]['weatherDesc'][0]['value']
print(f'?️ {city} 当前气温:{temp}°C,{desc}')
"

输出:

?️ 北京 当前气温:18°C,晴朗

整个过程不到 10 秒,连文件都不用创建。

再升级一下,改成交互式:

run
>> :lang py
>>> import requests
>>> def weather(city):
...   r = requests.get(f"http://wttr.in/{city}?format=j1").json()
...   t = r['current_condition'][0]['temp_C']
...   d = r['current_condition'][0]['weatherDesc'][0]['value']
...   return f"{city}: {t}°C, {d}"
...
>>> weather("上海")
'上海: 20°C, 多云'

是不是感觉开发效率飞起来了?


深入底层:run 是怎么实现的?

既然这么强大,那它是怎么做到的?我们来扒一扒它的技术架构。

? 架构概览

                +------------------+
                |     CLI Parser   |
                +--------+---------+
                         |
       +------------------+------------------+
       |                  |                  |
+------v------+   +-------v------+   +------v-------+
|  Language    |   |  Runtime     |   |  File/Code   |
|  Detector    |   |  Manager     |   |  Executor    |
+------+------+   +-------+------+   +------+-------+
       |                  |                  |
       +------------------+------------------+
                         |
                +--------v---------+
                |  Output Handler  |
                +------------------+

核心组件包括:

  1. CLI Parser:解析命令行参数
  2. Language Detector:根据扩展名或 -l 参数识别语言
  3. Runtime Manager:管理本地/远程运行时实例
  4. Executor:负责编译、运行、沙箱隔离
  5. Output Handler:统一输出格式,处理错误

⚙️ 关键技术点

1. 使用 Rust 的优势

作者选择 Rust 绝非偶然:

  • 零成本抽象:性能接近 C/C++,启动速度快(毫秒级)
  • 内存安全:避免空指针、野指针导致崩溃
  • 跨平台编译:一套代码生成 Win/macOS/Linux 二进制
  • 异步友好:内置 async/await,适合并发任务调度
  • Cargo 生态成熟:依赖管理清晰,发布流程自动化

2. 多语言调度机制

每种语言都有对应的“驱动器”(Driver),定义了:

  • 如何编译(如果有)
  • 如何运行
  • 依赖如何处理
  • 是否需要沙箱

例如 Python 驱动:

struct PythonDriver;
impl LanguageDriver for PythonDriver {
    fn compile(&self, _src: &str) -> Result<(), String> {
        Ok(()) // 解释型语言无需编译
    }

    fn run(&self, code: &str) -> Result<StringString> {
        letmut child = Command::new("python3")
            .arg("-c")
            .arg(code)
            .stdout(Stdio::piped())
            .spawn()
            .map_err(|e| e.to_string())?;

        let output = child.wait_with_output().map_err(|e| e.to_string())?;
        if output.status.success() {
            Ok(String::from_utf8(output.stdout).unwrap())
        } else {
            Err(String::from_utf8(output.stderr).unwrap())
        }
    }
}

而对于 Go,则要先写文件再编译:

fn run_go(code: &str) -> Result<StringString> {
    let temp_dir = TempDir::new("run_go")?;
    let file_path = temp_dir.path().join("main.go");
    fs::write(&file_path, code)?;

    let status = Command::new("go")
        .arg("run")
        .arg(file_path)
        .current_dir(temp_dir.path())
        .status()?;

    if status.success() {
        Ok("".into())
    } else {
        Err("Go execution failed".into())
    }
}

3. REPL 的状态管理

REPL 的难点在于“状态保持”。run 采用了一个全局 Context 结构体:

struct Context {
    variables: HashMap<String, Value>,
    current_lang: Language,
    history: Vec<String>,
}

每次执行代码后,将变量更新回 variables,并在切换语言时进行类型映射。

比如 Python 的 dict 转 JS 的 Object

fn py_dict_to_js_object(py_dict: PyDict) -> JsValue {
    let obj = js_sys::Object::new();
    for (k, v) in py_dict.iter() {
        let key = JsValue::from_str(k);
        let val = match v {
            PyObject::String(s) => JsValue::from_str(s),
            PyObject::Int(i) => JsValue::from(*i),
            _ => JsValue::NULL,
        };
        Reflect::set(&obj, &key, &val).unwrap();
    }
    obj.into()
}

虽然不能 100% 精确转换,但在大多数场景下够用了。


局限性 & 注意事项

再强大的工具也有短板,run 也不例外。

❌ 不适合生产部署

run 的定位是“快速实验、学习、调试”,而不是替代正式构建系统。

你不应该用它来跑线上服务,原因如下:

  • 缺乏完整的依赖管理
  • 没有构建缓存优化
  • 安全性较弱(沙箱可能被绕过)
  • 日志和监控能力有限

⚠️ 某些语言必须显式声明 --lang

比如 .m 文件可能是 Objective-C 也可能是 MATLAB,.pl 可能是 Perl 也可能是 Prolog。

所以在这些情况下,必须手动指定语言:

run --lang objc hello.m
run --lang matlab analyze.pl

否则会报错:“无法确定语言类型”。

? 小众语言支持尚不完善

虽然官方说支持 25+ 语言,但像 Haskell、Erlang、Clojure 这类函数式语言的支持还处于实验阶段。

尤其是涉及复杂依赖的项目(如 Cabal、Leiningen),目前还无法自动解析。


对比同类工具:run 到底赢在哪?

工具
支持语言
是否需预装环境
跨语言交互
启动速度
学习成本
npx
Node.js 为主
deno run
JS/TS
scriptisto
多语言
一般
playground
 类网站
多语言
慢(网络延迟)
run25+否(可选)
极快(本地二进制)

可以看到,run 在“本地化 + 多语言 + 交互性”三个方面做到了极致平衡。

特别是相比在线 Playground,它没有网络延迟、不依赖浏览器、能读写本地文件、支持管道操作——这才是真正的生产力工具。


教育领域的革命性应用

想象一下:

一个计算机老师上课讲“三种语言实现斐波那契数列”,以前他得分别打开三个终端,切换三个环境。

现在呢?

run
>> :lang py
>>> def fib(n): return n if n <= 1 else fib(n-1)+fib(n-2)
>>> fib(10)
55

>> :lang js
>>> const fib = n => n <= 1 ? n : fib(n-1) + fib(n-2);
>>> fib(10)
55

>> :lang rs
>>> fn fib(n: u32) -> u32 { if n <= 1 { n } else { fib(n-1) + fib(n-2) } }
>>> fib(10)
55

同一窗口,无缝切换,对比教学,直观高效。

学生回家也不用担心环境问题,只要装一个 run,就能继续练习。

这对降低编程学习门槛有着深远意义。


总结:未来已来,只是尚未普及

run 这个项目让我想起了当年 Docker 刚出现时的感觉——

“原来环境问题是可以被彻底解决的。”

它不是一个简单的命令封装工具,而是一种新的开发范式:

以开发者为中心,屏蔽底层差异,让代码即价值。

也许几年后,我们会习以为常地在一个终端里自由穿梭于 Python、Go、Rust、JS 之间,就像今天我们在 VS Code 里切换标签页一样自然。

而 run,或许就是这场变革的起点。


你可以马上动手试试的事

  1. 安装 run

    cargo install run-kit
  2. 测试你的第一段跨语言代码

    run --lang py --code "data = {'msg': 'Hello'}"
    :lang js
    console.log(data.msg)
  3. 写个实用小脚本
    比如把 Markdown 转 HTML(用 Pandoc):

    echo "# 标题\n这是内容" | run sh --code "pandoc -f markdown -t html | sed 's/^/<p>/; s/$/<\/p>/'"
  4. 贡献一份文档或示例
    项目欢迎 PR!你可以提交某个冷门语言的使用指南,或者添加新功能建议。


最后送大家一句鸡汤

“优秀的工具不会让你变得更聪明,但它会让你显得更高效。”

在这个信息爆炸的时代,谁掌握了高效的工具链,谁就掌握了时间的主动权。

而 run,正是这样一把打开效率之门的钥匙。

参考资料

[1] 

https://github.com/Esubaalew/run/releases: https://github.com/Esubaalew/run/releases



打赏

本文链接:https://kinber.cn/post/5710.html 转载需授权!

分享到:


推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

 您阅读本篇文章共花了: 

群贤毕至

访客