我想将 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。不好!</p>
像我这样的 child 会做什么?我正打算走命名管道或类似的荒野路线,但实际上,我需要知道的是如何让 awk 仅匹配来自 stderr 的模式。
最佳答案
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 查看
- 将 stdout 重定向回 stderr(它原来所在的位置)
- 将文件描述符 3 重定向回标准输出(它原来所在的位置)
附言这个解决方案是特定于 sh/bash 的。 Jonathan Leffler 说它也应该与 ksh 一起工作。如果您使用的是不同的 shell,您可以尝试找到用它执行相同重定向的语法——但如果那个不同的 shell 是 csh/tcsh,您可能就完蛋了。众所周知,cshell 在处理 stdout/stderr 方面很糟糕。
关于awk - 从 Awk 中读取 stderr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2508447/