【问题标题】:Capture output of cl-async:spawn捕获 cl-async:spawn 的输出
【发布时间】:2018-03-19 21:59:30
【问题描述】:

我希望尝试使用 cl-async 来运行一系列带有大量命令行参数组合的外部程序。但是,我不知道如何读取使用as:spawn 启动的进程的标准输出。

我通常会使用 uiop,它可以轻松捕获进程输出:

(let ((p (uiop:launch-program ... :output :stream)))
  (do-something-else-until-p-is-done)
  (format t "~a~%" (read-line (uiop:process-info-output p))))

我已经尝试了 as:spawn:output :pipe:output :stream 选项,并在我的退出回调中执行 (as:process-output process-object) 显示了适当的管道或异步流对象,但我不知道如何读取他们。

任何对此库有经验的人都可以告诉我如何做到这一点吗?

【问题讨论】:

    标签: common-lisp


    【解决方案1】:

    所以你去你的repl并输入:

    CL-USER> (documentation 'as:spawn 'function)
    

    然后您阅读所有出现的内容(或将您的观点放在符号上并点击C-c C-d f)。如果您阅读它,您会看到:input 等参数的格式为:pipe(:pipe args...):stream(:stream args...)(或其他一些选项)。 :stream 的行为与 :pipe 类似,但提供了不同类型的输出,有关 args 的详细信息,请查看 PIPE-CONNECT,因此您可以查找相关文档。好吧,它会告诉您选项是什么,但它不是很有用。 PIPESTREAM 的文档/描述是什么?事实证明,管道是STREAMISH 的一个类和一个子类。 PROCESS 那也是一个类,它有像PROCESS-OUTPUT 这样的插槽(和访问器)。那么,对于如何弄清楚下一步该做什么的好计划是什么?这里有一个建议:

    1. 使用:output :stream :input :pipe 说生成一个长时间运行的进程(如cat foo.txt -
    2. 检查结果 (C-c C-v TAB)
    3. 希望它是PROCESS 的一个实例。它的输出是什么?检查
    4. 希望输出是灰色流 (ASYNC-STREAM)。将其放入您的 repl 中,看看如果您尝试从中读取会发生什么?
    5. 那么输入呢?看看有什么类型,你可以用它做什么

    以上都是猜测。我没有尝试过运行任何这些,但你应该这样做。或者去看看库的源代码。它已经在你的电脑上,如果你找不到它在 GitHub 上。只有大约六个源文件,而且它们都很小。只需阅读它们,看看你能学到什么。或者转到您想了解的符号并点击M-. 直接跳转到它的定义。然后阅读代码。然后看看你是否能弄清楚该怎么做。

    【讨论】:

    • DESCRIBEDOCUMENTATION 更适合交互式使用。后者用于以编程方式访问文档字符串。
    • 这是真的。我想我只是想说明有文档。我认为在大多数情况下,最好的方法是结合使用来自 slime 的 lambda 列表提示并使用 M-.M-, 以及可能还有一点 grep 环顾四周
    【解决方案2】:

    我在测试套件中找到了答案。输出流只能通过读取回调异步处理。以下是后代的简单示例

    (as:start-event-loop
      (lambda ()
        (let ((bytes (make-array 0 :element-type '(unsigned-byte 8))))
            (as:spawn "./test.sh" '()
                      :exit-cb (lambda (proc exit-status term-signal)
                                  (declare (ignore proc exit-status term-signal))
                                  (format t "proc output:~%~a"
                                    (babel:octets-to-string bytes)))
                      :output (list :stream
                                    :read-cb (lambda (pipe stream)
                                               (declare (ignore pipe))
                                               (let ((buf (make-array 128 :element-type '(unsigned-byte 8))))
                                                 (loop for n = (read-sequence buf stream)
                                                    while (plusp n) do
                                                       (setf bytes 
                                                            (concatenate  '(vector (unsigned-byte 8))
                                                              bytes
                                                             (subseq buf 0 n)))))))))))
    

    $ cat test.sh
    #!/bin/bash
    
    sleep_time=$((1+$RANDOM%10))
    echo "Process $$ will sleep for $sleep_time"
    sleep $sleep_time
    echo "Process $$ exiting"
    

    产生预期的输出

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 2012-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多