从Awk内读取stderr

从Awk内读取stderr,awk,redirect,string-matching,Awk,Redirect,String Matching,我希望将SSH调试信息与其他输入分开(并记录)。但是,如果我只是将stderr重定向到一个日志文件,我就有可能将SSH的输出与主机上远程进程的输出相结合(这可能会向stderr发送一些信息): 因此,我只想筛选出那些与“debug1”匹配的行: 到目前为止还不错,但是ssh的调试输出将转到stderr。所以 $ ssh -v somemachine 2>& | awk '/debug1/ {print > "file.log"; next} {print}' 又失败了!我不

我希望将SSH调试信息与其他输入分开(并记录)。但是,如果我只是将stderr重定向到一个日志文件,我就有可能将SSH的输出与主机上远程进程的输出相结合(这可能会向stderr发送一些信息):

因此,我只想筛选出那些与“debug1”匹配的行:

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

$ ssh -v somemachine 2>& | awk '/debug1/ {print > "file.log"; next} {print}'
又失败了!我不想把stdout和stderr混在一起。糟糕


像我这样的孩子是干什么的?我本来打算使用命名管道或类似的方法,但实际上,我需要知道的是如何让awk只与stderr中的模式匹配。

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
按照顺序,这些重定向:

  • 将原始标准输出重定向到文件描述符3
  • 将stderr重定向到stdout以供awk查看
  • 将stdout重定向回stderr(原来的位置)
  • 将文件描述符3重定向回stdout(原来的位置)
注意:此解决方案是特定于sh/bash的。乔纳森·莱夫勒说,它也应该与ksh合作。如果您使用的是不同的shell,您可以尝试找到使用它执行相同重定向的语法-但是如果不同的shell是csh/tcsh,那么您可能就完蛋了。CShell在处理stdout/stderr方面是出了名的糟糕。

试试看(没有子shell):


请参阅。

非常感谢。。!我将ls与awk一起使用,无法重定向

我用过:

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


在将/debug1/引入管道时,您已经脱离了管道模型的期望。有什么原因不能在远程会话上记录stderr吗?请注意,awk只读取命名文件或标准输入;它不读stderr。因此,您必须将它读取的内容安排为'ssh'stderr输出。我只想记录ssh本身的stderr消息,并且仍然允许查看其他stderr消息。我将使用ssh远程运行一个命令:$ssh-v somemachine somecommands解决方案也应该适用于Bourne和Korn Shell;装饰性的贝壳会有问题。这就是为什么你最好把C壳留在海岸上,希望潮汐会把它们带走。你能避开双层外壳,同时执行:
1>&3
2>&1
重定向吗?按这个顺序?乔纳森:我不这么认为。这是我的测试:
(/foo|sed的/^/stdout:/'1>&32>&1|sed的/^/stderr:/'1>&2)3>&1
,其中
foo
向stdout和stderr各回一行。如果没有额外的子shell,则stderr行似乎可以干净地通过,好像2>&1重定向首先发生-我想不能保证订单会被保留?我的错-当您使用一个子shell时,订单会被保留,但是。。。1到3,然后2到1要去的地方,也就是3。
((ssh -v hostname somecommand 1>&3) 2>&1 | awk '/debug1/ ...' 1>&2) 3>&1
{ 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
FILES=`ls -lrt *.txt | awk '{print $9}' 2>> /dev/null`
FILES=`ls -lrt *.txt 2>> /dev/null | awk '{print $9}'`