如何捕获cl-async:spawn启动进程的标准输出?
解决cl-async中读取spawn进程标准输出的问题
我之前也踩过这个坑!cl-async是异步IO框架,和uiop那种同步阻塞的处理思路完全不一样——你不能用同步read-line那套逻辑来拿输出,得靠回调来处理异步推送的数据流。
你试过:output :pipe其实是对的,但关键是要绑定read-cb回调来接收输出,而不是试图同步读取。下面给你两个实用的示例:
实时打印进程输出
这个示例会在进程输出内容时实时打印:
(as:with-event-loop () (as:spawn "your-program" '("--arg1" "value1" "--arg2" "value2") :output :pipe ;; 每次读取到新输出时触发这个回调 :read-cb (lambda (data) ;; 注意:部分场景下data是字节数组,需要转成字符串 (let ((output-str (if (stringp data) data (babel:octets-to-string data)))) (format t "Process output: ~a~%" output-str))) ;; 进程退出时触发的回调 :exit-cb (lambda (exit-code signal) (format t "Process finished with exit code ~a (signal: ~a)~%" exit-code signal) (as:exit-event-loop))))
收集完整输出后再处理
如果需要等进程结束后拿到全部输出,可以用一个可调整数组来缓存:
(as:with-event-loop () ;; 初始化一个可动态扩展的字符串缓存 (let ((full-output (make-array 0 :element-type 'character :adjustable t :fill-pointer t))) (as:spawn "ls" '("-la") :output :pipe :read-cb (lambda (data) (let ((str (if (stringp data) data (babel:octets-to-string data)))) ;; 将新输出追加到缓存里 (format full-output "~a" str))) :exit-cb (lambda (exit-code signal) (format t "=== Full Process Output ===~%~a~%" full-output) (format t "Exit code: ~a~%" exit-code) (as:exit-event-loop)))))
关键注意点:
- 别试图在
as:spawn之后直接同步读取输出——cl-async的事件循环还没启动,异步IO操作根本没开始,你拿不到任何数据。 - 关于
data的类型:如果你的cl-async配置了使用字节流,回调会收到字节数组,这时候需要用babel:octets-to-string(确保你已经加载了babel库)转成字符串;如果是字符串模式,直接用就行。 - cl-async的核心是非阻塞异步回调,所有和进程IO相关的逻辑都要放到对应的回调里处理,这和uiop的同步阻塞模型是本质区别。
内容的提问来源于stack exchange,提问作者ptb
相关产品推荐
相关产品推荐

