我的脚本中有这个非常简单的函数:
# Used for debug tracing.
log()
{
:
echo "log: $1"
}
这个想法是能够在一个地方自定义/关闭日志记录。非常粗糙。
现在我希望我的脚本在发布配置中完全不产生输出。我想到的唯一解决方案,但非常不干燥:
TMPFILE='/tmp/tempfilewithpossiblyuniquename'
cmd 1>"$TMPFILE" 2>"$TMPFILE"
cat "$TMPFILE" | xargs log
rm "$TMPFILE"
为了每一个命令。对此如何改进呢?
编辑:我想收集全部输出到stdout
和stderr
并通过 进行引导log()
。然后log()
可以选择忽略一切、记录到文件、打印等。
答案1
首先,该函数只会记录发送给它的任何内容的第一个“单词”,因为您使用$1
而不是"$*"
.
其次,有无数种方法可以完成这类事情(POSIX 经常出现这种情况)。我可能会选择类似的东西:
log() {
cat - >> "$logfile"
}
do_stuff | log
但你也可以:
(
do_stuff
do_more_stuff
) >> "$logfile"
至于完全抑制所有输出——这通常最好留给调用环境(例如./thing 1> /dev/null 2> &1
),而不是像以前那样将其锁定在“代码中”。那是说:
squashout="true" # comment this out to stop killing output
if ! [[ "true" = "${squashout-false}" ]]; then
# Redirect stdout and stderr to the null device.
exec 1> /dev/null
exec 2> /dev/null
fi
答案2
绝对没有简单的输出,只需将脚本的stdout
和重定向stderr
到/dev/null
:
exec >/dev/null 2>&1
这将影响 shell 本身以及它之后执行的任何命令。有条件地运行该命令以选择输出重定向的位置。
if [ "$output_to_file" = 1 ]; then
exec > "$outputfilename" 2>&1
elif [ "$output_suppress" = 1 ]; then
exec > /dev/null 2>&1
fi
注意,抑制全部输出可能不是一个好主意。用户很可能想要一些错误通知。
如果您坚持通过该函数传递输出(并且正在运行 Bash/ksh/Zsh),您可以使用进程替换:
#!/bin/bash
mangle_output() {
# do something smarter here
while read -r line; do
echo "output: $line";
done;
}
# redirect stdout and stderr to the function
exec > >(mangle_output) 2>&1
echo something that produces output
尽管请注意,使用 shell 循环处理输出并不是一个好主意,但至少它很慢。看:为什么使用 shell 循环处理文本被认为是不好的做法?。如果您想要的只是重定向一个文件,或者重定向到/dev/null
,只需使用exec
设置重定向。