【问题标题】:READING stderr from within Awk从 awk 中读取 stderr
【发布时间】:2010-03-24 14:27:51
【问题描述】:

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

再次被挫败!我不想混合标准输出和标准错误。糟糕!

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

【问题讨论】:

  • 在您将 /debug1/ 引入管道时,您已经超出了管道模型的预期。您是否有原因无法在远程会话上记录标准错误?
  • 注意awk只读取命名文件或标准输入;它不读取标准错误。因此,您必须将其读取的内容安排为“ssh”标准错误输出。
  • 我只想从 ssh 本身记录 stderr 消息,并且仍然允许看到其他 stderr 消息。我将使用 ssh 远程运行命令:$ ssh -v somemachine somecommand

标签: awk redirect string-matching


【解决方案1】:

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

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

【讨论】:

  • 该解决方案也适用于 Bourne 和 Korn shell;装饰性的贝壳会有问题。这就是为什么你最好把 C 贝壳留在海边,希望潮水会把它们带走。
  • 你能避免双子shell并同时执行1>&32>&1重定向吗?
  • @Jonathan:我不这么认为。这是我的测试:(./foo | sed 's/^/stdout: /' 1>&3 2>&1 | sed 's/^/stderr: /' 1>&2) 3>&1 其中foo 将一行回显到 stdout 和 stderr。如果没有额外的子外壳,stderr 行似乎干净利落地通过,好像 2>&1 重定向首先发生 - 我想不能保证订单被保留?
  • 我的错 - 当你使用一个子外壳时,顺序被保留,但是...... 1 到 3,然后 2 到 1 去的地方 - 这也是 3。
【解决方案2】:

试试这个(没有子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

【讨论】:

    【解决方案3】:

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

    我用过:

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

    现在:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多