2017-02-10 57 views
0

在关于这类事情的previous question中,我学习了如何在成功的情况下访问命令的输出,以及在出错时执行其他代码。但是,通常情况下,打印命令的输出以防错误更有意义。这解决了其他问题的代码是:如何在发生错误时获取系统命令的输出?

(with-output-to-string 
    (lambda() 
    (unless (system "ls -la") 
     ;; handle error here 
    ))) 

我如何获得系统命令的形式unless里面的输出?

使用示例:我想运行一些系统命令,只想打印“成功!”到终端,如果命令成功,并在错误的情况下,我想打印“错误!”加上命令的实际输出。

注意:我不想两次运行该命令,因为许多系统命令有副作用,我不想触发两次,只是为了获得输出并且这样的第二次调用的输出可能不同于无论如何都是第一次调用,因此可能不会反映实际的错误。

回答

2

过程process产生一个包含五个值的列表,其中两个是输入端口(从子进程的stdout和stderr传送),last是一个可用于获取子进程的退出代码的过程。例如,

> (process "someCommand") 
'(#<input-port:subprocess-stdout> 
    #<output-port:subprocess-stdin> 
    11292 
    #<input-port:subprocess-stderr> 
    #<procedure:control>) 

要获得子进程的退出代码,在最后一个项目叫(这是一个过程)的说法'exit-code,因为这样的:

((last (process "someCommand")) 'exit-code) 

但需要注意的是,上述如果子进程仍在运行,则过程返回#f而不是整数,因此首先使用参数'wait调用它,然后用'exit-code调用它。例如,

> (define cmd (process "someCommand")) 
> ((last cmd) 'wait) 
> ((last cmd) 'exit-code) ; should now return an integer 

退出代码现在可以进行比较,并且在于,它是不为零的情况下,stderr输入端口可以被读取和打印。

下面是在错误的情况下,其产生"Success!"如果子过程执行成功的样本函数,并打印"Error! + error-message"

(define (output command) 
    (define cmd (process command)) 
    ((last cmd) 'wait) 
    (define exit-code ((last cmd) 'exit-code)) 
    (if (= exit-code 0) 
     "Success!" 
     (printf "Error!\n~a\n" (read-line (fourth cmd))))) 

例如;

> (output "date") 
Success! 
> (output "ls -al") 
Success! 
> (output "someCommand") 
Error! 
/bin/sh: 1: someCommand: not found 
+0

我注意到,可以多次调用'read-line',它似乎是一个迭代器。我打印所有的行。我只需要比较'#'。是否有更好的方法来打印完整的输出? – Zelphir

+0

使用我创建的答案中提供的内容:https://gist.github.com/ZelphirKaltstahl/2d229948cf0486854bd9e1a17589189a – Zelphir

+0

您可以使用[read-string](https://docs.racket-lang.org/reference/Byte_and_String_Input。 html#%28def ._%28%28quote._〜23〜25kernel%29. 29.read-string%29%29)而不是'read-line'从输入端口读取多行。例如,'(read-string 10000(fourth cmd))'会读取多达10000个字符,或者如果之前遇到'eof',则停止并返回字符串。您可以将10000更改为适合您需要的数字。 – assefamaru

相关问题