2010-03-24 61 views
2

我想让SSH调试信息与其他输入保持分离(并记录)。但是,如果我只是stderr重定向到一个日志文件,我的风险来自远程进程在主机上结合从SSH和输出输出(即可能送东西到stderr):从Awk中读取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的模式。

+0

由您介绍/ DEBUG1 /插入管道的地步,你已经走出的管道模型所期待的。有没有理由不能在远程会话上记录stderr? – msw 2010-03-24 14:39:15

+0

请注意,awk只读取命名文件或标准输入;它不读stderr。所以,你必须安排它读取的是'ssh'stderr输出。 – 2010-03-24 14:52:34

+0

我只想从ssh本身记录stderr消息,并仍然允许看到其他stderr消息。我将用ssh远程运行一个命令: $ ssh -v somemachine somecommand – Dave 2010-03-24 15:34:24

回答

5

Awk实际上看不到来自stderr的输入 - 管道只管道stdout。为了做你想做的事,你将不得不改变重定向的方向。如果你关心在标准输出上有什么,你必须做一些更复杂的

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

:如果你不关心在标准输出上有什么答案是非常简单的。我相信,这将工作:

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

为了,那些重定向:

  • 重定向原来标准输出一旁文件描述符3
  • 重定向错误输出到标准输出awk的看
  • 重定向stdout返回到stderr(它原来的位置)
  • 将文件描述符3重定向到标准输出(它最初是在哪里)

P.S.这个解决方案是sh/bash特有的。 Jonathan Leffler说它也应该和ksh一起工作。如果你使用的是不同的shell,你可以尝试找到语法来做同样的重定向 - 但是如果这个不同的shell是csh/tcsh,你可能只是搞砸了。 cshells在处理stdout/stderr方面臭名昭着。

+0

该解决方案也可以在Bourne和Korn shell上运行;这是装饰性的海贝壳会有问题。这就是为什么你最好把C壳放在海边,希望潮水能把它们带走。 – 2010-03-24 14:48:43

+0

您可以避免使用双重子shell,并按照以下顺序同时执行:1&3和2&1重定向吗? – 2010-03-24 14:50:41

+1

@Jonathan:我不这么认为。这是我的测试:'(./foo | sed's/^/stdout:/'1&3 2&1 | sed's/^/stderr:/'1&2)3>&1'其中'foo'将stdout和stderr各回响一行。如果没有额外的子shell,那么stderr行似乎会干净地通过,就好像2>&1重定向首先发生 - 我想这不能保证订单被保存了吗? – Cascabel 2010-03-24 14:53:07

0

这给一试(无子shell):

{ 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

0

非常感谢..!我用awk使用了ls,但无法重定向。

我用:

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

现在:

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