我想将 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}'

又被挫败了!我不想混合标准输出和标准错误。坏的!

像我这样的 child 做什么?我正要走命名管道的路线或一些类似的野心,但实际上,我需要知道的是如何让 awk 仅匹配来自 stderr 的模式。

最佳答案

Awk 实际上无法看到来自 stderr 的输入——管道只通过管道输出标准输出。为了做你想做的事,你将不得不考虑重定向。如果您不关心标准输出上的内容,答案非常简单:

(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
  • 将 stderr 重定向到 stdout 以便 awk 查看
  • 将标准输出重定向回标准错误(原先所在的位置)
  • 将文件描述符 3 重定向回标准输出(原来的位置)

  • 附言此解决方案是特定于 sh/bash 的。 Jonathan Leffler 说它也应该与 ksh 一起使用。如果您使用的是不同的 shell,您可以尝试找到对其进行相同重定向的语法 - 但如果该不同的 shell 是 csh/tcsh,您可能只是被搞砸了。众所周知,cshell 在处理 stdout/stderr 方面很糟糕。

    关于awk - 从 awk 中读取 stderr,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2508447/

    10-16 20:17