Bash:管道stdout并将stderr捕获到变量中

时间:2016-02-24 11:25:13

标签: bash stdout stderr

是否可以将正常stdout进一步传播到另一个程序,但将stderr存储到变量中?

这是用例:

mysqldump database | gzip > database.sql

在这种情况下,我想捕获mysqldump生成的所有错误/警告,并将它们存储到变量中,但正常的stdout(转储)应继续通过管道传递给{{ 1}}。

关于如何实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:3)

您可以执行以下操作:

mysqldump database 2> dump_errors | gzip > database.sql
error_var=$( cat dump_errors )
rm dump_errors

此处,mysqldump之前的所有错误都会重定向到名为' dump_errors'的文件,而stdout会通过管道传送到gzip,然后database.sql会写入$ sort 1> output 2> errors # redirects stdout to "output", stderr to "errors" $ sort 1> output 2>&1 # stderr goes to stdout, stdout writes to "output" $ sort 2> errors 1>&2 # stdout goes to stderr, stderr writes to "errors" $ sort 2>&1 > output # tie stderr to screen, redirect stdout to "output" $ sort > output 2>&1 # redirect stdout to "output", tie stderr to "output"

' dump_errors'的内容然后分配给变量' error_val'和文件' dump_errors'然后被删除。

请注意以下重定向:

WITH ss_query AS  (
      SELECT    *
      FROM  tbl_data
  )
  , rowgen as (select /*+materialize()*/level yr from dual connect by level <= 3)
  , dates as (select /*+materialize()*/to_date(substr(c001,1,2)||'0401','yymmdd') fy_start from ss_query where line = 2)
select equipment_name
, date_start
, date_end
, max(cost) cost
, max(speed) speed
from (
  select 
    case when upper(c001) like '%COST%' then substr(c001,1,instr(upper(c001),'COST')-2)
      when upper(c001) like '%SPEED%' then substr(c001,1,instr(upper(c001),'SPEED') -2)
    end equipment_name,
    add_months(fy_start,12 * (yr - 1)) date_start,
    add_months(fy_start,12 * (yr))-1 date_end,
    case when upper(c001) like '%SPEED%' then
      case when yr = 1 then c002
          when yr = 2 then c003
          when yr = 3 then c004
        end 
      end speed,
    case when upper(c001) like '%COST%' then
      case when yr = 1 then c002
          when yr = 2 then c003
          when yr = 3 then c004
        end 
      end cost
  from ss_query ,
        rowgen,
        dates
  where line > 2
)
where speed is not null or cost is not null
group by equipment_name, date_start, date_end
order by equipment_name, date_start;

答案 1 :(得分:1)

您可以执行以下操作:

errors=$(mysqldump database 2>&1 > >(gzip > database.sql))

在这里,我使用流程替换来使gzipmysqldump的输出用作stdin。给定the order of redirections (2>&1 before >)mysqldump的stderr现在应该用于命令替换。

测试出来:

$ a=$(sh -c 'echo foo >&2; echo bar' 2>&1 > >(gzip > foo))
$ gunzip < foo
bar
$ echo $a
foo