问题
Dear StackExchange members,
I recently began toying around with Common Lisp and want to create a web interface for administrating a modded Minecraft server. I already tried out this solution but in this case the function just hangs and never returns.
My code looks like this:
(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)))
How can I get a string containing the complete process output till that time without having to wait for it to terminate?
回答1:
Experimenting with /bin/cat
, I found some things that might help you.
First, of all, always use finish-output
after writing to the process's input:
(format (process-input *cat*) "Hello~%")
(finish-output (process-input *cat*))
Otherwise, the input may not reach the subprocess until you close the input stream. If Minecraft requires input before it'll generate any output, then trying to read from its output without the required input would result in SBCL hanging in a way that can't be recovered with C-c C-c in SLIME.
Second, use listen
to determine if any output has been generated:
(when (listen (process-output *cat*))
(read-line (process-output *cat*)))
With finish-output
and listen
, I was able to avoid hanging while incrementally reading from cat's stdout.
来源:https://stackoverflow.com/questions/30414250/sbcl-gather-output-of-run-program-process-while-running