Bash 从未重定向的管道接收 stderr

Bash 从未重定向的管道接收 stderr

如果调用而不先重定向它,是否可以foo.sh从内部接收/重定向 stderr :?bar.shfoo.sh | bar.sh

foo.sh

#!/bin/bash
echo "hello world" >&2

酒吧.sh

#!/bin/bash
sed -Eu 's/world/everyone/g'
user@pc$ ./foo.sh | ./bar.sh
hello world

user@pc$ ./foo.sh 2>&1 | ./bar.sh
hello everyone

bar.sh即使用户意外地像第一个示例中那样调用它,是否可以使行为像第二个示例一样?

顺便说一句,foo.sh可以是任何写入stderr.我只是对如何从 接收它感兴趣bar.sh

答案1

由于这个想法是过滤掉 stderr 上的数据,因此有一种更好的方法可以做到这一点,而无需合并流或丢失所有 stderr:my_command 2> >(grep --invert-match secret_regex >&2)

语法解释:

  • 2>说“将标准错误发送到命令中的下一个单词”
  • >(some_command)说把它之前的东西发送到标准输入命令的。
  • >&2最后发送grep输出(行不是匹配秘密)回到标准错误。

示例,显示 stdout 和 stderr 在过滤后如何完好无损:

$ (echo output; echo error >&2; echo secret >&2) 2> >(grep --invert-match secret >&2)
output
error
$ ((echo output; echo error >&2; echo secret >&2) 2> >(grep --invert-match secret >&2)) 2>/dev/null
output
$ ((echo output; echo error >&2; echo secret >&2) 2> >(grep --invert-match secret >&2)) >/dev/null
error

原始答案:当您调用 时./foo.sh | ./bar.sh,标准错误foo.sh会出现在 shell 设置的任何位置(即在两个命令运行之前)。我不认为(没有根访问权限)可以bar.sh“劫持”标准错误所指向的位置,因为这将是一个很大的安全漏洞:恶意进程可能会劫持某些打印敏感信息的命令的输出。

答案2

bash提供一个简写:

如果|&使用时,command 的标准错误除了其标准输出外,还通过管道连接到 command2 的标准输入;它是简写2>&1 |

相关内容