Bash 脚本 - 将 stderr 存储在变量中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3130375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash script - store stderr in a variable
提问by thornate
I'm writing a script to backup a database. I have the following line:
我正在编写一个脚本来备份数据库。我有以下几行:
mysqldump --user=$dbuser --password=$dbpswd \
--host=$host $mysqldb | gzip > $filename
I want to assign the stderr to a variable, so that it will send an email to myself letting me know what happened if something goes wrong. I've found solutions to redirect stderr to stdout, but I can't do that as the stdout is already being sent (via gzip) to a file. How can I separately store stderr in a variable $result ?
我想将 stderr 分配给一个变量,以便它会向自己发送一封电子邮件,让我知道如果出现问题会发生什么。我找到了将 stderr 重定向到 stdout 的解决方案,但我不能这样做,因为 stdout 已经被发送(通过 gzip)到一个文件。如何将 stderr 单独存储在变量 $result 中?
回答by Adam Crume
Try redirecting stderr to stdout and using $()
to capture that. In other words:
尝试将 stderr 重定向到 stdout 并使用它$()
来捕获它。换句话说:
VAR=$((your-command-including-redirect) 2>&1)
Since your command redirects stdout somewhere, it shouldn't interfere with stderr. There might be a cleaner way to write it, but that should work.
由于您的命令将 stdout 重定向到某处,因此它不应干扰 stderr。可能有一种更简洁的方式来编写它,但这应该可行。
Edit:
编辑:
This really does work. I've tested it:
这确实有效。我已经测试过了:
#!/bin/bash
BLAH=$((
(
echo out >&1
echo err >&2
) 1>log
) 2>&1)
echo "BLAH=$BLAH"
will print BLAH=err
and the file log
contains out
.
将打印BLAH=err
并且文件log
包含out
.
回答by Joat
For any generic command in Bash, you can do something like this:
对于 Bash 中的任何通用命令,您可以执行以下操作:
{ error=$(command 2>&1 1>&$out); } {out}>&1
Regular output appears normally, anything to stderr is captured in $error (quote it as "$error" when using it to preserve newlines). To capture stdout to a file, just add a redirection at the end, for example:
常规输出正常出现,任何 stderr 都会在 $error 中捕获(使用它来保留换行符时将其引用为“$error”)。要将标准输出捕获到文件,只需在末尾添加重定向,例如:
{ error=$(ls /etc/passwd /etc/bad 2>&1 1>&$out); } {out}>&1 >output
Breaking it down, reading from the outside in, it:
分解它,从外到内阅读,它:
- creates a file description $out for the whole block, duplicating stdout
- captures the stdout of the whole command in $error (but see below)
- the command itself redirects stderr to stdout (which gets captured above) then stdout to the original stdout from outside the block, so only the stderr gets captured
- 为整个块创建文件描述 $out,复制标准输出
- 在 $error 中捕获整个命令的标准输出(但见下文)
- 命令本身将stderr重定向到stdout(在上面被捕获)然后stdout从块外部重定向到原始stdout,所以只有stderr被捕获
回答by hlovdal
You can save the stdout reference from before it is redirected in another file number (e.g. 3) and then redirect stderr to that:
您可以在将 stdout 引用重定向到另一个文件号(例如 3)之前将其保存,然后将 stderr 重定向到该引用:
result=$(mysqldump --user=$dbuser --password=$dbpswd \
--host=$host $mysqldb 3>&1 2>&3 | gzip > $filename)
So 3>&1
will redirect file number 3 to stdout (notice this is before stdout is redirected with the pipe). Then 2>&3
redirects stderr to file number 3, which now is the same as stdout. Finally stdout is redirected by being fed into a pipe, but this is not affecting file numbers 2 and 3 (notice that redirecting stdout from gzip is unrelated to the outputs from the mysqldump command).
所以3>&1
会将文件号 3 重定向到 stdout(注意这是在使用管道重定向 stdout 之前)。然后2>&3
将 stderr 重定向到文件号 3,它现在与 stdout 相同。最后,stdout 被送入管道重定向,但这不会影响文件号 2 和 3(请注意,从 gzip 重定向 stdout 与 mysqldump 命令的输出无关)。
Edit: Updated the command to redirect stderr from the mysqldump
command and not gzip
, I was too quick in my first answer.
编辑:更新命令以从命令重定向 stderrmysqldump
而不是gzip
,我在第一个答案中太快了。
回答by msw
dd
writes both stdout and stderr:
dd
写入标准输出和标准错误:
$ dd if=/dev/zero count=50 > /dev/null
50+0 records in
50+0 records out
the two streams are independent and separately redirectable:
这两个流是独立的并且可以单独重定向:
$ 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
if you really needed a variable:
如果你真的需要一个变量:
$ variable=`cat countfile`