如何将错误重定向到文件?

如何将错误重定向到文件?

我有一个简单的脚本,它将输出重定向append到一个文件。

filename="/home/ronnie/tmp/hello"

date=$(date)
echo "$date" >> $filename

现在,假设我更改date=$(date)date= $(date)会产生错误。

我修改后的脚本:

filename="/home/ronnie/tmp/hello"

date= $(date)
echo "$date" >> $filename 2>> $filename 
#Also tried echo "$date" >> $filename 2>&1

我认为上面的脚本会将错误重定向test.sh: line 5: Fri: command not found到文件hello,但它只是在文件中输入一个新行,并且错误会打印在我的stdout.

我的 bash 版本:

ronnier@ronnie:~/tmp$ bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)

那么,我哪里出错了。

答案1

导致错误的行是date =$(date),该错误被发送到 stderr。在此阶段,您不会将 stderr 重定向到任何地方。后续行将 stderr 发送到 $filename,但这不是导致错误的行。

获得所需效果的方法之一是运行脚本并同时将 stderr 定向到其他地方,因此,

./myscript 2>> errors.txt

此时,errors.txt 将包含您的错误。

所以问题是,生成错误的行是脚本本身的错误,而不是由脚本调用的外部命令引起的错误,该命令的输出被重定向。即它是您需要重定向的顶级脚本输出。

答案2

shell 在到达第 5 行时发出错误消息。此时 shell 的错误流不会重定向。

如果您编写date= $(date) 2>/dev/null,“找不到命令”消息来自 shell,而不是来自错误流被重定向的命令。因此您仍然会看到错误消息。

为了避免看到错误消息,请将整个命令放入一个组中,并从整个组重定向错误流:

{ date= $(date); } 2>/dev/null

使用大括号时,该命令仍然在父 shell 中执行,因此它可以更改其环境和其他状态(不是在这里执行的)。您还可以将命令放入函数体或子 shell 中(括号内的命令,在单独的 shell 进程中执行)。

exec您可以通过在不带命令名的内置命令上使用重定向来永久重定向 shell 的文件描述符(或至少直到下次更改它们为止) 。

exec 2>/dev/null
# From this point on, all error messages are lost
date= $(date)
exec 2>/some/log/file
# From this point on, all error messages go to the specified file

相关内容