如何远程操作REPL

之前在知乎上回答了一个问题:《如何可以让全世界lisper在同一个REPL的不同终端下一起工作?》

以下为我的原回答:

楼主说的应该是让Lisp的REPL支持远程连接吧?

Slime环境下比较简单,就是让后端的Swank监听个端口,再映射出来就可以了,官方文档中有述:SLIME User Manual, version 2.11: Connecting to a remote lisp

之所以可以这样工作,是因为Common Lisp本身工作机制,它运行在REPL环境下,这样能动态修改内存中的数据,这样就可以实现热补丁了。

我用Common Lisp做WEB开发时,会在才上线程序后开启一个远程的REPL一段时间,这样如果遇到bug,我就可以本地给运行在远程的Lisp程序动态打热补丁,而不用一系列的流程:打包、上传,甚至先中断服务,再部署新代码。当然这种开发模式更加适合个人开发,而不是团队开发。

另外相传NASA的飞船在太空呆了半年后,发现代码中的一个bug会导致系统出错,他们就连接到远程的REPL给Lisp代码打的热补丁。

实践起来其实只需几个简单的步骤:

1、在远程服务器中的Common Lisp镜像中加载Swank,可直接用Quicklisp:

(ql:quickload "swank")

2、启动Swank服务,默认监听端口为4005,指定:PORT参数可以修改端口号:

(swank:create-server)

3、在本地使用SSH做端口转发,将远程的4005端口转发到本地的4005端口上:

ssh -L4005:127.0.0.1:4005 shellcodes.org

4、本地启动Emacs并执行:

M-x slime-connect 回车 回车

这时在本地的Slime中启动的镜像实质上对应的是远程服务器上运行的Lisp镜像,在REPL中做的任何操作都是在远程生效的。

简单来说,Common Lisp代码运行在镜像(Image)之中,好比进程运行在操作系统之上。而Swank则是Emacs和Lisp镜像之间的通讯协议,上面的操作步骤只是做了一个端口转发而已。

这种方式对那种不能中断的服务打热补丁、修改功能、增加新功能等等来说是极其有用的。

有关Swank协议,详细可参考:https://github.com/astine/swank-client/blob/master/swank-description.markdown