SBCL:运行时收集运行程序进程的输出

时间:2015-05-23 15:11:16

标签: subprocess common-lisp sbcl

亲爱的StackExchange会员,

我最近开始使用Common Lisp,并希望创建一个用于管理模拟Minecraft服务器的Web界面。我已经尝试了this solution,但在这种情况下,该函数只是挂起而永远不会返回。

我的代码如下所示:

(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)))

如何获取一个包含完整流程输出的字符串,直到那时不必等待它终止?

1 个答案:

答案 0 :(得分:4)

尝试使用str("fortran"),我发现了一些可能对您有帮助的事情。

首先,在写入流程的输入后总是使用/bin/cat

finish-output

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

其次,使用(format (process-input *cat*) "Hello~%") (finish-output (process-input *cat*)) 确定是否已生成任何输出:

listen

使用(when (listen (process-output *cat*)) (read-line (process-output *cat*))) finish-output,我可以避免在从猫的标准输出中逐渐读取时挂起。