将标准错误通过管道传输到文件并将其保留在标准错误中?

将标准错误通过管道传输到文件并将其保留在标准错误中?

我有一个脚本(片段),正在记录其输出和标准错误:

#!/bin/sh
#...
{
   date "+%Y-%m-%d %T"
   cd $workdir
   ls -ltr validfile badfile #example command that provides stdout, stderr
} | tee -a $logfile

如果我执行上述操作,我会在日志文件中获得标准输出。要在那里也获得标准错误,我可以这样做:

#!/bin/sh
#...
{
   date "+%Y-%m-%d %T"
   cd $workdir
   ls -ltr validfile badfile
} 2>&1 | tee -a $logfile

但是,当从命令行调用脚本中的此版本时,我无法解析错误:

$ ./script.sh 2>/dev/null

将仅显示所有标准输出和标准错误。如果这次我只想将错误置为无效怎么办?

您能向我演示如何将标准错误传送到日志,但在通过命令行或其他脚本调用时将其保留在标准错误上吗?

AIX 7.1,ksh(无 bash)

答案1

使用一些奇特的输出重定向,可以在不使用基本 bash 重定向到进程的情况下实现这一点。

记录标准错误并将其保存在标准错误管道上

#!/bin/sh
exec 4>&1    # important as it "saves" stdout (usually /dev/tty2 for example)
exec 3>&1    # work-in-progress file descriptor
logfile=/var/log/myscript.out

{
   {
      date "+%Y-%m-%d %T"
      cd $workdir
      ls -ltr validfile badfile
   } 2>&1 1>&3 | tee -a $logfile 1>&2 2>/dev/null 3>&4
} 3>&1 | tee -a $logfile

exec 4>&-   # proper form is to clean up when you're done
exec 3>&-

解释:
exec 4>&1exec 3>&1创建新的文件描述符 3 和 4,它们都指向标准输出所指向的内容(很可能是您的终端)。

2>&1将整个第二级花括号的标准错误重定向到标准输出。1>&3将标准输出重定向到 fd3 指向的任何内容(这是标准输出,但不在管道 1 中,这很重要!)

| tee -a $logfile将标准输入(来自第二级花括号,即旧的 stderr)复制到日志文件和标准输出。1>&2移动标准输出到标准错误(所以回到它所属的位置).2>/dev/null可能没有必要,但它会重定向来自 tee 的任何错误输出并将其丢弃。3>&4将管道 3 重定向到管道 4(顺便说一下,它指向 stdout,还记得吗?)。

3>&1取出第一级括号中的 3 号管道并将其发送到常规标准输出.| tee -a $logfile捕获标准输入(即括号中的[调整后的]标准输出)并将其复制到日志和标准输出。

相关内容