代码之家  ›  专栏  ›  技术社区  ›  Dave

从awk中读取stderr

  •  3
  • Dave  · 技术社区  · 15 年前

    我想将ssh调试信息与其他输入分开(并记录)。但是,如果我只是将stderr重定向到一个日志文件,我就有可能将ssh的输出和主机上远程进程的输出(即 可以 发送内容到stderr):

    $ ssh -v somemachine 2> file.log
    

    所以,我只想过滤掉那些与“debug1”匹配的行:

    $ ssh -v somemachine | awk '/debug1/ {print > "file.log"; next} {print}'
    

    到目前为止还不错,但是ssh的调试输出将转到stderr。所以…

    $ ssh -v somemachine 2>& | awk '/debug1/ {print > "file.log"; next} {print}'
    

    又失败了!我不想把stdout和stderr混在一起。糟糕!

    像我这样的孩子是做什么的?我本来打算走命名管道的路线,或者说是一些这样的疯狂,但实际上,我只需要知道如何让awk只匹配stderr中的模式。

    3 回复  |  直到 15 年前
        1
  •  6
  •   Cascabel    15 年前

    awk实际上看不到来自stderr的输入-仅管道的管道stdout。为了做你想做的事,你必须在重定向上下功夫。如果你不关心stdout上的内容,答案很简单:

    (ssh -v hostname somecommand > /dev/null) 2>&1 | awk '/debug1/ ...'
    

    如果你关心stdout上的内容,你将不得不做一些更复杂的事情。我相信这是可行的:

    ((ssh -v hostname somecommand 1>&3) 2>&1 | awk '/debug1/ ...' 1>&2) 3>&1
    

    按照顺序,这些重定向:

    • 将原始stdout重定向到文件描述符3
    • 重定向stderr到stdout以便awk看到
    • 将stdout重定向回stderr(原来的位置)
    • 将文件描述符3重定向回stdout(原来的位置)

    p.s.这个解决方案是特定于sh/bash的。乔纳森·莱夫勒说,它也应该与ksh合作。如果您使用的是不同的shell,您可以尝试找到语法来对其执行相同的重定向—但是如果不同的shell是csh/tcsh,那么您很可能就是搞砸了。cshells在处理stdout/stderr方面非常糟糕。

        2
  •  0
  •   Dennis Williamson    15 年前

    试试这个(没有子外壳):

    { ssh -v somemachine 2>&1 1>&3- | awk '/debug1/ {print > "file.log"; next} {print}'; } 3>&1
    

    { ssh -v somemachine 2>&1 1>&3- | grep debug1 > file.log; } 3>&1
    

    this .

        3
  •  0
  •   j0k gauthamp    13 年前

    谢谢。。!我用的是带锥子的ls,无法重定向。

    我用过:

    FILES=`ls -lrt *.txt | awk '{print $9}' 2>> /dev/null`
    

    现在:

    FILES=`ls -lrt *.txt 2>> /dev/null | awk '{print $9}'`
    
    推荐文章