重定向回 shell 中的 stderr

重定向回 shell 中的 stderr

由于我错误地在 SO 中使用 bash shell 标签询问并认为这是一个更合适的地方,因此我重新提出了我的问题。

我正在 AWS DataPipeline 中编写一个连接到关系数据库的 shell 脚本,即使对于 SQL 错误,退出代码也是 0,因此我需要捕获 + 重定向 stderr。

我将 stderr 重定向到另一个文件以检查其内容,但仍然希望填充 stderr。原因是 DataPipeline 捕获所有 stderr 和 stdout 并将它们全部放入 1 个日志中。由于重定向,它不会从失败的 sql 命令中捕获 stderr。有没有办法仍然填充 stderr?我目前拥有的是:

/bin/snowsql -f /home/scripts/dev/dev.sql 2> /home/scripts/dev/stderr.txt

以下内容适用于 Bash:

/bin/snowsql -f /home/scripts/dev/dev.sql 2> >(tee /home/scripts/dev/stderr.txt >&2)

我找不到 shell 进程替换的正确语法。在 shell 中执行上述操作相当于什么?

答案1

在 中sh,您只能通过管道将 stdout 传递给另一个命令,因此您必须首先交换 stdout 和 stderr:

/bin/snowsql -f /home/scripts/dev/dev.sql 3>&2 2>&1 >&3 3>- | tee /home/scripts/dev/stderr.txt

重定向是从左到右执行的,除了管道,它是在一开始创建的,所以它的作用是:

  1. 打开管道并在其中重定向 stdout ( |)
  2. 复制 stderr 并将文件描述符 3(任意)重定向到它,以便稍后重用它 ( 3>&2)
  3. 复制 stdout(当前重定向到管道)并将 stderr 重定向到它 ( 2>&1)
  4. 重复文件描述符 3(当前在原始 stderr 中重定向)并将 stdout 重定向到它 ( >&3)
  5. 关闭文件描述符 3 ( 3>-)

在这种状态下,我们交换了 stdout 和 stderr,并且管道接收 stderr。然后我们让它tee完成将 stderr 写入文件的工作,并在自己的 stdout 上再次输出它。

感谢这个 StackOverflow 答案的提示:https://stackoverflow.com/a/2381643

相关内容