Pergunta

Estou tentando descobrir como usar o fluxo de saída de um programa que começo RUN-PROGRAM Portanto, pode ser usado como a entrada de outro programa começou com RUN-PROGRAM (ou seja, o equivalente moral e talvez literal da tubulação). Eu tentei usar várias combinações do :INPUT, :OUTPUT e :WAIT Argumentos de palavras -chave, mas nada que eu acabei foi produtivo até agora. Quaisquer dicas serão úteis; por exemplo, como eu iria fazer algo como ls | grep lisp da concha?

Uma das minhas tentativas é

(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))))) 

Executar isso em um lodo Repl faz com que tudo fique pendurado até eu quebrar com C-c C-c, então, obviamente, não é a coisa certa, mas não tenho certeza de como alterá -lo, por isso é a coisa certa.

EDITAR: Adicionando :WAIT NIL para ambos RUN-PROGRAM invocações, ou apenas para a invocação para grep, não faz o truque. Nesse caso, a função vai pendurar e quebrar com C-c C-c recebe um rastreamento de pilha indicando que há uma função local (definida via FLET) chamado SB-UNIX:SELECT Isso pendurou.

Foi útil?

Solução

Recebi uma resposta funcional de Raymond Toy On Comp.lang.lisp. Sua solução era para CMUCL, mas funcionou com o essencialmente idêntico RUN-PROGRAM Função no SBCL intimamente relacionado e, com pequenas mudanças, também funcionará no CCL, porque o CCL's RUN-PROGRAM é basicamente um clone do CMUCL/SBCL.

O segredo, por assim dizer, é configurar o ls processar primeiro e depois fornecer seu fluxo de saída para o grep Processar como entrada, assim:

(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))))) 

Eu também experimentei omitir o :WAIT NIL argumento do RUN-PROGRAM chamar para ls, e funcionou da mesma forma.

Outras dicas

Tente adicionar :wait nil para seus argumentos para run-program. Isso deve ter o seu grep e seu LS em segundo plano. Como está, você está iniciando o processo Grep, esperando que isso termine e, em seguida, inicia o LS que pretende alimentar no processo de Grep. Infelizmente, como você está esperando o grep terminar, você nunca chega tão longe.

De forma semelhante, mas talvez não seja a sua pergunta, você pode fazer:

(with-output-to-string (s)
      (ccl:run-program "sh" (list "-c" "ls a/directory/somewhere/*.lisp") :output s)
      s)

ou

(with-output-to-string (s)
      (ccl:run-program "sh" (list "-c" "ls /a/directory/somewhere/*.lisp | wc -l") :output s)
      s)

ou

(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)

E, claro, você pode usar

(format nil "ls ~a" directory)

Para obter informações, você pode fazer algo como:

(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)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top