Я пытаюсь выяснить, как использовать поток вывода одной программы, с которой я запускаю RUN-PROGRAM
таким образом, это может использоваться в качестве входа другой программы, запущенной с RUN-PROGRAM
(т.е. мораль и возможно литеральный эквивалент передачи по каналу). Я попытался использовать много комбинаций :INPUT
, :OUTPUT
и :WAIT
аргументы ключевого слова, но ничто, на что я натолкнулся, не было продуктивно до сих пор. Любые подсказки были бы полезны; например, как я пошел бы о выполнении чего-то как 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)))))
Выполнение этого в СЛИЗИ, которую REPL заставляет все подвешивать, пока я не порываю C-c C-c
, таким образом, это - довольно очевидно, не правильная вещь, но я не уверен, как изменить его так, это - правильная вещь.
Править: Добавление :WAIT NIL
обоим RUN-PROGRAM
вызовы, или только к вызову для grep
, не добивается цели. В этом случае функция зависнет, и разрыв C-c C-c
получает отслеживание стека, указывающее, что существует локальная функция (определенный через FLET
) названный SB-UNIX:SELECT
это зависло.
Я получил рабочий ответ от Раймонда Тоя на comp.lang.lisp . Его решение было для CMUCL, но оно работало с практически идентичной функцией RUN-PROGRAM
на тесно связанном SBCL, и с небольшими изменениями оно будет работать и на 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
для ls
, и это сработало так же хорошо.
Попробуйте добавить : wait nil
к вашим аргументам в run-program
. При этом и grep, и ls должны работать в фоновом режиме. Как есть, вы запускаете процесс grep, ожидаете его завершения, а затем запускаете ls, которые вы собираетесь передать процессу grep. Увы, так как вы ждете завершения grep, вы никогда не зайдете так далеко.