在bash脚本中是否有可能进行所有输出,除了我专门使用回声输出的输出,请转到日志文件,但是如果输出中存在错误,则应显示在终端(以及日志文件也当然)?
这是您可以使用附加文件描述符来做的:
#!/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 "%sn" "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
命令和所有错误的输出。 - 在日志文件中,我们会收到错误并将其保留在脚本中。
unix终端通常提供两个输出文件销售商, stdout
和 stderr
,这两者默认为终端。
行为良好的程序将其"标准"输出发送到stdout
,并向stderr
发送错误。因此,例如echo
写信给Stdout。grep
将匹配行写入stdout
,但是如果出现问题,例如无法读取文件,则错误将转到stderr
。
您可以用>
(用于stdout
)和2>
(对于stderr
)重定向。所以:
myscript >log 2>errors
将输出写入log
,并将错误写入errors
。
因此,可以简单地满足您的一部分要求:
command >log
...错误将继续通过Stdout进入终端。
您的额外要求是"除了我专门输出Echo的输出"。
您的 echo
s转到stderr可能足够了:
echo "Processing next part" >&2
>&2
将stdout
从此命令重定向到stderr
。这是在Shell脚本中输出错误(有时是信息输出)的标准方法。
如果您需要更多的内容,则可能需要使用更多文件描述符来做些更复杂的事情。尝试:https://unix.stackexchange.com/questions/18899/when-would-you-use-use-an-additional-file-descriptor
表现良好的UNIX程序倾向于避免使用额外的文件描述符进行复杂的事情。惯例是将自己限制在stdout
和stderr
中,并在命令行参数中指定任何进一步的输出为文件名。