我正在试图弄清楚如何使用我以RUN-PROGRAM
开头的一个程序的输出流,因此它可以用作以RUN-PROGRAM
开头的另一个程序的输入(即道德也许字面上相当于管道)。我尝试过使用:INPUT
,:OUTPUT
和:WAIT
个关键字参数的多种组合,但我没有碰到任何内容
到目前为止一直很有成效。任何提示都会有所帮助;例如,我如何从shell中执行类似ls | grep lisp
的操作?
我的一次尝试是
(defun piping-test ()
(let ((grep-process (run-program "/usr/bin/grep" '("lisp")
:input :stream
:output :stream)))
(unwind-protect
(with-open-stream (s (process-input grep-process))
(let ((ls-process (run-program "/bin/ls" '()
:output s)))
(when ls-process
(unwind-protect
(with-open-stream (o (process-output grep-process))
(loop
:for line := (read-line o nil nil)
:while line
:collect line))
(process-close ls-process)))))
(when grep-process (process-close grep-process)))))
在SLIME REPL中运行它会导致一切都挂起,直到我中断
与C-c C-c
,所以它显然不是正确的,但我是
不知道如何改变它,所以这是正确的。
编辑:将:WAIT NIL
添加到RUN-PROGRAM
个调用,或仅添加grep
的调用,并不能解决问题。在这种情况下,函数将挂起,并且与C-c C-c
断开会获得一个堆栈跟踪,指示存在已挂起的名为FLET
的本地函数(通过SB-UNIX:SELECT
定义)。
答案 0 :(得分:10)
我在comp.lang.lisp得到了Raymond Toy的工作答案。他的解决方案是针对CMUCL的,但它在密切相关的SBCL上使用了基本相同的RUN-PROGRAM
函数,并且稍微改变它也适用于CCL,因为CCL的RUN-PROGRAM
基本上是一个克隆一个来自CMUCL / SBCL。
秘密就是首先设置ls
进程,然后将其输出流作为输入提供给grep
进程,如下所示:
(defun piping-test2 ()
(let ((ls-process (run-program "/bin/ls" '()
:wait nil
:output :stream)))
(unwind-protect
(with-open-stream (s (process-output ls-process))
(let ((grep-process (run-program "/usr/bin/grep" '("lisp")
:input s
:output :stream)))
(when grep-process
(unwind-protect
(with-open-stream (o (process-output grep-process))
(loop
:for line := (read-line o nil nil)
:while line
:collect line))
(process-close grep-process)))))
(when ls-process (process-close ls-process)))))
我还尝试省略:WAIT NIL
对RUN-PROGRAM
的{{1}}调用中的ls
参数,它的效果也很好。
答案 1 :(得分:1)
尝试将:wait nil
添加到run-program
的参数中。这应该让你的grep和你的ls在后台运行。你正在启动grep进程,等待完成,然后启动你想要进入grep进程的ls。唉,既然你在等待grep完成,你就永远不会那么远。
答案 2 :(得分:1)
相关地,但也许没有发现你的问题,你可以这样做:
(with-output-to-string (s)
(ccl:run-program "sh" (list "-c" "ls a/directory/somewhere/*.lisp") :output s)
s)
或
(with-output-to-string (s)
(ccl:run-program "sh" (list "-c" "ls /a/directory/somewhere/*.lisp | wc -l") :output s)
s)
或
(with-output-to-string (s)
(ccl:run-program "ssh" (list "a-user@some-ip" "sh -c ls /a/directory/somewhere/on/remote/server/*.lisp | wc -l") :output s)
s)
当然,你可以使用
(format nil "ls ~a" directory)
要获得输入,您可以执行以下操作:
(with-output-to-string (out)
(format t "~%Enter your sudo password:~%")
(with-input-from-string (s (read))
(ccl:run-program "ssh" (list *remote* "sudo cat /etc/init.d/nginx") :input s :output out))
out)