以下工作原理:
(let* ((i (make-string-input-stream "foo bar baz"))
(p (sb-ext:run-program "/bin/cat" '()
:input i :output *trace-output* :wait t)))
(sb-ext:process-close p))
下面的代码没有 - 它会在写完" 001":
后停止(let* ((_1 (format t "001~%"))
(p (sb-ext:run-program "/bin/cat" '()
:input :stream :output *trace-output* :wait t))
(_2 (format t "010~s~%" p))
(s (sb-ext:process-input p)))
(declare (ignore _1 _2))
(format s "foo bar baz~%")
(finish-output s)
(sb-ext:process-close p))
所以它似乎在sb-ext:run-program
中默默地执行。
这是在Ubuntu 16.04.1上的SBCL 1.3.6。
有什么想法吗?提前谢谢,弗兰克
答案 0 :(得分:3)
正如我在评论中提到的,问题是:WAIT T
参数。它会导致对SB-EXT:RUN-PROGRAM
的调用在子进程退出之前不会返回。
在第一个示例中,您将字符串输入流传递给子进程。 cat
将读取流中的输入,当输入结束时将出现文件结束,因此cat
退出。在第二个示例中,没有可用于程序的输入,因此它实际上是一个无限循环(就像在命令行上运行cat
一样,并且不给它任何输入;它永远不会退出。)
解决方案是使用:WAIT NIL
。您还必须使用CLOSE
关闭输入流,否则将不会有EOF,cat
会继续侦听更多输入。关闭流后,您还希望使用SB-EXT:PROCESS-WAIT
等待cat
退出。
(let* ((p (sb-ext:run-program "/bin/cat" '()
:input :stream
:output *standard-output*
:wait nil))
(s (sb-ext:process-input p)))
(format s "foo bar baz~%")
(finish-output s)
(close s)
(sb-ext:process-wait p)
(sb-ext:process-close p))
我不确定您为什么使用*TRACE-OUTPUT*
作为子输出,因此我将其更改为*STANDARD-OUTPUT*
。
另外,使用FORMAT
进行调试就好了。 Common Lisp提供实际的调试工具。在这种情况下,您可以使用STEP
:
(step (let* ((p (sb-ext:run-program "/bin/cat" '()
:input :stream
:output *standard-output*
:wait nil))
(s (sb-ext:process-input p)))
(format s "foo bar baz~%")
(finish-output s)
(close s)
(sb-ext:process-wait p)
(sb-ext:process-close p)))
这将使您进入调试器,显示接下来要评估的调用。您可以调用STEP-NEXT
- 重新启动以继续下一次呼叫。
答案 1 :(得分:0)
这是有效的,正如jkiiski所建议的那样:
(let* ((p (sb-ext:run-program "/bin/cat" '()
:input :stream
:output *standard-output*
:wait nil))
(s (sb-ext:process-input p)))
(format s "foo bar baz~%")
(finish-output s)
(sb-ext:process-wait p)
(sb-ext:process-close p))