Bash脚本 - 将stderr存储在变量中

时间:2010-06-28 06:06:54

标签: bash scripting redirect stdout stderr

我正在编写一个备份数据库的脚本。我有以下几行:

mysqldump --user=$dbuser --password=$dbpswd  \
   --host=$host $mysqldb | gzip > $filename

我想将stderr分配给变量,以便它会向我发送一封电子邮件,让我知道如果出现问题会发生什么。我找到了将stderr重定向到stdout的解决方案,但我不能这样做,因为stdout已经被发送(通过gzip)到一个文件。如何将stderr分别存储在变量$ result中?

4 个答案:

答案 0 :(得分:76)

尝试将stderr重定向到stdout并使用$()来捕获它。换句话说:

VAR=$((your-command-including-redirect) 2>&1)

由于你的命令在某处重定向stdout,它不应该干扰stderr。可能有一种更清晰的方式来编写它,但这应该有效。

修改

这确实有效。我测试了它:

#!/bin/bash                                                                                                                                                                         
BLAH=$((
(
echo out >&1
echo err >&2
) 1>log
) 2>&1)

echo "BLAH=$BLAH"

将打印BLAH=err,文件log包含out

答案 1 :(得分:17)

对于Bash中的任何通用命令,您可以执行以下操作:

{ error=$(command 2>&1 1>&$out); } {out}>&1

正常输出正常显示,stderr的任何内容都在$ error中捕获(当使用它来保留换行符时将其引用为“$ error”)。要将stdout捕获到文件,只需在末尾添加重定向,例如:

{ error=$(ls /etc/passwd /etc/bad 2>&1 1>&$out); } {out}>&1 >output

打破它,从外面读,它:

  • 为整个块创建文件描述$ out,复制stdout
  • 以$ error(但见下文)
  • 捕获整个命令的标准输出
  • 命令本身将stderr重定向到stdout(上面被捕获),然后stdout从块外部转移到原始stdout,因此只有stderr被捕获

答案 2 :(得分:4)

您可以在将stdout引用重定向到另一个文件编号(例如3)之前将其保存,然后将stderr重定向到:

result=$(mysqldump --user=$dbuser --password=$dbpswd  \
   --host=$host $mysqldb 3>&1 2>&3 | gzip > $filename)

所以3>&1会将文件号3重定向到stdout(注意这是在stdout被管道重定向之前)。然后2>&3将stderr重定向到文件号3,现在与stdout相同。最后,stdout被送入管道重定向,但这不会影响文件编号2和3(注意,从gzip重定向stdout与mysqldump命令的输出无关)。

编辑:更新了命令以从mysqldump命令而不是gzip重定向stderr,我的第一个答案太快了。

答案 3 :(得分:0)

dd写了stdout和stderr:

$ dd if=/dev/zero count=50 > /dev/null 
50+0 records in
50+0 records out

这两个流是独立的,可单独重定向:

$ dd if=/dev/zero count=50 2> countfile | wc -c
25600
$ cat countfile 
50+0 records in
50+0 records out
$ mail -s "countfile for you" thornate < countfile

如果你真的需要一个变量:

$ variable=`cat countfile`