在 ssh-blog 里使用 Monkey
bin/monkey 是本站在 bin/ 里自己放的一个程序,不是 ssh-blog 框架自带的命令。对访客来说,它和普通命令一样:输入名字就能跑,也可以接管道、重定向。
浏览器终端
打开首页,在提示符后面输入:
visitor@localhost:/$ monkey
终端就交给了解释器。之后每行输入一条完整的 Monkey 代码:
let square = fn(x) { x * x };
map([1, 2, 3, 4], square)
[1, 4, 9, 16]
退出方式:
- 输入
@@; - 或者按 Ctrl-D;
- Ctrl-C 直接中断解释器,回到伪 bash(
$?会变成非 0)。
解释器运行在服务端。刷新或关闭页面、空闲 5 分钟,进程都会被收掉,REPL 里的变量和宏不会保留。
SSH 交互
按首页横幅里的提示 ssh 进来,然后和浏览器里一样:
$ ssh -p 443 你的站点
visitor@localhost:/$ monkey
网页和 SSH 交互会话都会分配 pty,所以提示符、回显、Ctrl-C / Ctrl-D 都正常。
一次性命令
$ ssh -p 443 你的站点 'monkey -e "1 + 1"'
2
$ ssh -p 443 你的站点 'monkey -e "map([1, 2, 3, 4], fn(x) { x * x })"'
[1, 4, 9, 16]
没有申请 pty 时,解释器自动进入批处理:没有横幅、没有 >> ,只输出结果,适合放进脚本。加 -t 可以强制走交互模式。
管道和重定向
Monkey 在伪 bash 里就是一个普通命令:
visitor@localhost:/$ echo "1 + 1" | monkey
2
visitor@localhost:/$ monkey -e "map([1, 2, 3], fibonacci)" | cat
[1, 1, 2]
写到文件:
visitor@localhost:/$ monkey -e "let a = 3; a" > out.txt
visitor@localhost:/$ cat out.txt
3
注意 let 只是赋值,没有值:
visitor@localhost:/$ monkey -e "let a = 3" > empty.txt
visitor@localhost:/$ cat empty.txt
这里不会打印任何东西,empty.txt 是 0 字节。这和在 REPL 里输入 let a = 3; 不打印结果是一致的;想输出值就写 let a = 3; a。
> 写的是你自己的虚拟视图,不碰服务器磁盘。刷新页面或者 reset 之后,out.txt 就没了。
退出码也会传回来:
visitor@localhost:/$ monkey -e "nope"
Identifier not found: nope
visitor@localhost:/$ echo $?
1
伪 bash 的 $? 只区分 0 和非 0。
跑脚本
仓库里有一个可以直接运行的示例:
visitor@localhost:/$ cat posts/monkey/demo.monkey
visitor@localhost:/$ monkey posts/monkey/demo.monkey
120
[1, 4, 9, 16, 25]
55
15
路径按当前目录算:上面的命令是在 / 下写的;如果已经 cd posts/monkey,就改成 monkey demo.monkey。
monkey 是外部程序,文件参数由它自己按真实工作目录打开;伪 bash 里的 /posts/... 这种虚拟绝对路径只对内置命令有效。所以在哪个目录,就用相对那个目录的路径最稳。
交互模式按行解析,多行函数要写在一行里;多行程序放进脚本文件,用 monkey 文件 运行最省事。
案例文件
posts/monkey/ 下有几份 .txt,每一份开头都用 // 注释写了运行方式。它们既是网页上的纯文本,也是可以直接执行的 Monkey 脚本。表格里的命令假设当前在 /;如果已经 cd posts/monkey,把 posts/monkey/ 前缀去掉:
| 文件 | 内容 | 运行 |
|---|---|---|
case_function.txt |
函数、闭包、递归 | monkey posts/monkey/case_function.txt |
case_collection.txt |
数组、哈希、高阶函数 | monkey posts/monkey/case_collection.txt |
case_macro.txt |
宏 unless / when |
monkey posts/monkey/case_macro.txt |
case_pipeline.txt |
把输出交给管道和重定向 | monkey posts/monkey/case_pipeline.txt |
网页上可以直接打开 /posts/monkey/case_function.txt 读源码,终端里 cat 同一份文件,monkey 读它执行。输出都可以继续接 | head、| grep、| wc,或者 > report.txt。
命令行参数
monkey [选项] [脚本]
-e 代码 求值一段代码后退出
-q 不打印开场横幅
-v 显示版本
visitor@localhost:/$ monkey -v
monkey 1.0.0
不给脚本和 -e 时读标准输入:标准输入是终端就是交互式 REPL,否则逐行批处理。
和伪 bash 的其他配合
help里有一组“程序”,列出bin/下可运行的文件;which monkey会告诉你它是外部程序,以及文件在仓库里的位置;man monkey给出外部程序的简要说明;- Tab 补全会把
monkey算进候选。
它不是 ssh-blog 的内置命令。换一份 ssh-blog 部署,需要自己把程序放进那棵树的 bin/ 里;程序需要满足的接口见仓库里的 bin/README.md。