Bash - 将所有输出发送到日志文件,但显示错误

时间:2016-12-02 16:29:02

标签: bash shell unix file-descriptor io-redirection

在bash脚本中是否可以使所有输出(除了输出i特别用echo输出)转到日志文件,但是如果输出中的错误应该显示在终端中(并且日志文件也是当然的)?

2 个答案:

答案 0 :(得分:1)

通过使用附加文件描述符,您可以执行以下操作:

#!/bin/bash

# open fd=3 redirecting to 1 (stdout)
exec 3>&1

# redirect stdout/stderr to a file but show stderr on terminal
exec >file.log 2> >(tee >(cat >&3))

# function echo to show echo output on terminal
echo() {
   # call actual echo command and redirect output to fd=3
   command echo "$@" >&3
}

# script starts here
echo "show me"
printf "=====================\n"
printf "%s\n" "hide me"
ls foo-foo
date
tty
echo "end of run"

# close fd=3
exec 3>&-

运行脚本后,它将在终端上显示以下内容:

show me
ls: cannot access 'foo-foo': No such file or directory
end of run

如果你cat file.log,则会显示:

=====================
hide me
ls: cannot access 'foo-foo': No such file or directory
Fri Dec  2 14:20:47 EST 2016
/dev/ttys002
  • 在终端上,我们只输出echo命令和所有错误。
  • 在日志文件中,我们收到错误并从脚本中继续输出。

答案 1 :(得分:0)

UNIX终端通常提供两个输出文件描述符stdoutstderr,默认情况下都会转到终端。

表现良好的程序将其“标准”输出发送到stdout,将错误发送到stderr。例如,echo写入stdout。 grep将匹配的行写入stdout,但如果出现问题,例如无法读取文件,则错误会转到stderr

您可以使用>(适用于stdout)和2>(适用于stderr)重定向这些内容。所以:

 myscript >log 2>errors

将输出写入log,将错误写入errors

因此,只需使用以下内容即可满足您的部分要求:

 command >log

...错误将继续通过stdout传递到终端。

您的额外要求是“除了输出我专门用echo输出”。

你的echo去stderr:

可能已经足够了
 echo "Processing next part" >&2

>&2将此命令的stdout重定向到stderr。这是在shell脚本中输出错误(有时是信息输出)的标准方法。

如果您需要更多,可能需要使用更多文件描述符来执行更复杂的操作。尝试:https://unix.stackexchange.com/questions/18899/when-would-you-use-an-additional-file-descriptor

表现良好的UNIX程序往往避免使用额外的文件描述符来处理复杂的事情。惯例是将自己限制为stdoutstderr,并在命令行参数中将任何其他输出指定为文件名。