在检查函数的退出状态和抑制输出时使用 shell 内置时间

fut*_*eal 4 bash time

我正在尝试在 bash 脚本中执行以下操作,并且想知道是否有可能:

  • 使用 time
  • 抑制命令的 stdout 输出
  • 在出现错误时捕获命令的 stderr 输出
  • 运行后查看命令的退出状态码

这是一个复杂的链,我没有太多运气让它一起工作。如果我停止使用时间,我可以获得状态代码。

这是我到目前为止所拥有的:

# the setup
TIMEFORMAT=%R
MYSQL=mysql <options>

# execute and time a query (does more than is listed here)
function executeQuery {

  TIME=$( time ( $MYSQL "$1" 2>&1 | tee /tmp/somefile.txt > /dev/null ) 2>&1 )

  # do something with $?

}
Run Code Online (Sandbox Code Playgroud)

我正在使用 tee 将命令中的任何错误响应重定向到文件,然后将生成的 stdout 发送到 /dev/null。然后我将时间命令的 stderr 重定向到 stdout,它应该以 $TIME 结束。

现在,如果我将该行更改为:

  TIME=$( time ( $MYSQL "$1" 2>&1 | tee /tmp/somefile.txt > /dev/null; exit ${PIPESTATUS[0]} ) 2>&1 )
Run Code Online (Sandbox Code Playgroud)

它正确地从 mysql 发回退出代码,但破坏了时间命令。

这甚至可能吗?我错过了什么吗?希望目标很明确。

谢谢!

Der*_*rfK 7

bashtime是一个主要的 PITA。如果没有像您的多级子 shell 那样讨厌的 shell hack,它的输出是不可重定向的。 http://mywiki.wooledge.org/BashFAQ/032表明正确答案是:

TIME = $( ( time $MYSQL "$1" 2>&1 | tee /tmp/somefile.txt > /dev/null; exit ${PIPESTATUS[0]} ) 2>&1 )
Run Code Online (Sandbox Code Playgroud)

请注意,bashtime将整个管道作为参数,因此将子shell 放在时间调用之后是不正确的。

这是经过测试的

TIME = $( ( time ls /asdfasfdsfs 2>&1 | tee asdf 2>&1 >/dev/null ; exit ${PIPESTATUS[0]} ) 2>&1 );
echo $?;
echo $TIME
Run Code Online (Sandbox Code Playgroud)

这给了我

2
real 0m0.003s user 0m0.004s sys 0m0.004s
Run Code Online (Sandbox Code Playgroud)