2010-06-28 124 views
34

我在写脚本来备份数据库。我有以下行:Bash脚本 - 在变量中存储stderr

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

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

回答

57

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

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

由于您的命令将stdout重定向的地方,它不应该有标准错误干扰。可能有更清晰的方式来编写它,但这应该起作用。

编辑:

这确实工作。我测试过它:

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

echo "BLAH=$BLAH" 

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

+0

我不认为这有效。 stderr被重定向到stdout,然后被重定向到一个文件。你不能将命令的stdout重定向到一个文件,然后用stderr替换显示的stdout – 2010-06-28 06:23:59

+0

@Michael:看我的编辑。 – 2010-06-28 06:30:04

+0

完美的作品。谢谢! – thornate 2010-06-28 08:02:26

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` 
4

你可以将stdout引用从另一个f中重定向之前保存ile数字(例如3),然后重定向标准错误到:

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

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

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

8

对于猛砸任何通用的命令,你可以做这样的事情:

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

常规输出显示正常,什么标准错误用它来当$错误捕获(引号,如“$错误”保留换行符)。要捕获标准输出到一个文件,只是在末尾添加一个重定向,例如:

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

其分解,从课外阅读,它:

  • 用于创建一个文件描述$出整个块,复制标准输出
  • 捕获$错误整个命令的标准输出(但是参见下文)
  • 命令本身标准错误重定向到标准输出(其被上述捕获),然后从块外部标准输出到原来的标准输出,所以只有stderr才能获得captu红色
+1

在bash v3.2中不起作用:''意外的令牌'{out}'''。这个语法是否需要Bash 4? – 2013-06-18 17:58:16

+0

它在bash 4.2和4.1中运行良好,我甚至尝试过shopts:compat32,compat31,它也可以在那里工作,也许它是3.2中的一个bug,因为bash在兼容模式下工作,除非兼容性只包含项目那会不会因为4.2而破裂,而不是4.2的一部分功能......(我想大多数人使用4.2这几天是对的?)无论如何,这是一个旧帖子,但只是为了清除它,它确实有效,正是我需要在屏幕上显示正常文本时将错误分配给变量... :) – osirisgothra 2014-04-03 16:25:53