SBCL:在 运行ning 期间收集 运行-程序进程的输出

SBCL: Gather output of run-program process while running

亲爱的 StackExchange 会员,

我最近开始玩弄 Common Lisp,想创建一个 Web 界面来管理修改后的 Minecraft 服务器。我已经尝试过 this solution 但在这种情况下函数只是挂起而不会 returns.

我的代码如下所示:

(defvar *proc*)

(defun create-minecraft-proc ()
  (let* ((binary "/usr/bin/java")
    (jar "/home/user/temp/Vanilla 1.8/minecraft.jar")
    (dir "/home/user/temp/Vanilla 1.8")
    (args (list "-jar" jar "nogui")))
    (setf *proc* (sb-ext:run-program binary args :directory dir :wait nil :input :stream :output :stream))))

(defun copy-stream (in out)
  (loop for line = (read-line in nil nil)
     while line
       do (write-line line out)))

(defun get-minecraft-output ()
  (with-open-stream (proc-stream (process-output *proc*))
    (with-output-to-string (out)
      (copy-stream (process-output *proc*) out)))

我怎样才能得到一个包含完整进程输出的字符串,而不必等待它终止?

试验 /bin/cat,我发现了一些可能对您有帮助的东西。

首先,在写入进程的输入后始终使用finish-output

(format (process-input *cat*) "Hello~%")
(finish-output (process-input *cat*))

否则,在您关闭输入流之前,输入可能无法到达子进程。如果 Minecraft 在生成任何输出之前需要输入,那么 尝试在没有所需输入的情况下读取其输出将导致 SBCL 以无法在 SLIME 中使用 C-c C-c 恢复的方式挂起。

其次,使用listen判断是否有输出产生:

(when (listen (process-output *cat*))
    (read-line (process-output *cat*)))

使用 finish-outputlisten,我能够避免在从 cat 的标准输出中增量读取时挂起。