64

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

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

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

4

4 回答 4

102

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

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

由于您的命令将标准输出重定向到某处,因此它不应干扰标准错误。可能有一种更简洁的方式来编写它,但这应该可以。

编辑:

这确实有效。我已经测试过了:

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

echo "BLAH=$BLAH"

将打印BLAH=err并且文件log包含out.

于 2010-06-28T06:19:46.280 回答
22

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

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

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

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

将其分解,从外向内阅读,它:

  • 为整个块创建文件描述 $out,复制 stdout
  • 在 $error 中捕获整个命令的标准输出(但见下文)
  • 该命令本身将 stderr 重定向到 stdout(在上面捕获),然后从块外部将 stdout 重定向到原始 stdout,因此只有 stderr 被捕获
于 2011-06-11T19:07:09.573 回答
5

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

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

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

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

于 2010-06-28T06:25:17.287 回答
0

dd写入标准输出和标准错误:

$ 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`
于 2010-06-28T06:22:07.897 回答