【问题标题】:How do I redirect errors to /dev/null in bash?如何在 bash 中将错误重定向到 /dev/null?
【发布时间】:2015-08-09 07:01:42
【问题描述】:

我们每天运行 Selenium 测试来测试我们的网站和扩展程序。我写了一个脚本(根据this question)来计算通过和失败的测试数量。这是脚本:

#!/bin/bash

today=`TZ='Asia/Tel_Aviv' date +"%Y-%m-%d"`
yesterday=`TZ='Asia/Tel_Aviv' date +"%Y-%m-%d" -d "yesterday"`

...

print_test_results()
{
    declare -i passed_tests=0
    declare -i failed_tests=0
    declare -i total_tests=0
    log_suffix="_${file_name}.log"
    yesterday_logs="${log_prefix}${yesterday}_[1,2]*${log_suffix}"
    today_logs="${log_prefix}${today}_0*${log_suffix}"
    for temp_file_name in $yesterday_logs $today_logs ; do
        total_tests+=1
        if grep -q FAILED "$temp_file_name" ; then
            failed_tests+=1
        elif grep -q OK "$temp_file_name" ; then
            passed_tests+=1
        else
            failed_tests+=1
        fi
    done
    echo "<tr>"
    echo "<td>$test_name - $today</td>"
    if [ $passed_tests = "0" ]; then
        echo "<td>$passed_tests passed</td>"
        echo "<td><span style=\"color: red;\">$failed_tests failed</span></td>"
    else
        echo "<td><span style=\"color: green;\">$passed_tests passed</span></td>"
        echo "<td>$failed_tests failed</td>"
    fi
    echo "<td>$total_tests tests total</td>"
    echo "</tr>"
}

file_name="chrome_gmail_1_with_extension_test"
test_name="Chrome Gmail 1 With Extension Test"
print_test_results

...

但问题是,如果文件不存在 (in $yesterday_logs $today_logs),我会收到错误消息。如何将这些错误消息重定向到 /dev/null?我想将它们从脚本重定向到 /dev/null,而不是从调用脚本的行 - 我希望这个脚本永远不会显示有关不存在的文件的错误消息。

【问题讨论】:

标签: bash


【解决方案1】:

仅作记录:

一般来说,要抑制 bash 中的错误消息,请使用 command 2&gt;/dev/null。所以在你的情况下,你应该使用grep -q OK 2&gt;/dev/null

但正如您的案例也表明(从我在 cmets 中读到的内容),这是一件有风险的事情,因为它掩盖了您的代码中可能存在的错误。 “我希望这个脚本永远不会打印错误消息”只有在知道可能发生的所有个可能的错误情况时才应该说。

【讨论】:

  • 嗨@Alfe,grep -q OK 还不够,因为我对每个文件进行两次grep。如何将2&gt;/dev/null 添加到命令for temp_file_name in $yesterday_logs $today_logs ; do ...
  • 当然,重定向只适用于它所应用的命令,因此您必须在您启动的每个命令 (grep) 上重复该短语。要将其应用于范围,请像这样附加它:for i in …; do …; done 2&gt;/dev/null, i。 e.就在它的最后,在关闭done 之后;那么该范围内的所有命令都会受到影响。
  • 谢谢,我接受这个答案,因为这就是我的意思,我只是不知道把2&gt;/dev/null 放在哪里。
  • @Uri:正如@Alfe 本人在他的回答中所补充的那样,这是一件有风险的事情。如果您按照我的建议使用shopt -s nullglob,那么grep 甚至不会在不存在的文件名上运行。
  • 通常情况下,glob 模式(如foo*)将扩展为所有匹配的文件名,以空格分隔(如fooone footwo foothree)并且如果有no 匹配文件名,它将扩展为自身(即扩展至foo*)。在这种正常情况下,像grep 这样的程序将收到与文件名不匹配的全局模式,因此它通常会失败(file not found)。使用 shell 选项 shopt -s nullglob,与任何现有文件名不匹配的 glob 模式将被完全删除(从命令中删除参数),因此 grep 不会得到错误的文件名。
【解决方案2】:

在您的脚本中,您可以将此行放在开头:

shopt -s nullglob

如果您的 glob 模式没有找到任何匹配的文件,这将不匹配任何内容。否则,当您使用以下内容时,将返回整个 glob 模式:

for temp_file_name in $yesterday_logs $today_logs; do ... done

【讨论】:

  • 是的,它有效。我接受这个答案。我在 date -d 命令中有错字,这就是我收到错误消息的原因。
【解决方案3】:

最终我将这一行改为:

for temp_file_name in `ls $yesterday_logs $today_logs 2>/dev/null` ; do
    total_tests+=1
    if grep -q FAILED "$temp_file_name" ; then
        failed_tests+=1
    elif grep -q OK "$temp_file_name" ; then
        passed_tests+=1
    else
        failed_tests+=1
    fi
done

那么只有ls 错误被定向到/dev/null

【讨论】:

  • 这个解决方案有几个问题。 ①$yesterday_logs等中的空格会给你带来麻烦。使用双引号来避免这种情况,即使当前的实现肯定没有空格。事情会随着时间而改变。 ② 使用ls 列出所有目录项也有类似的问题,例如。 G。如果任何条目包含空格或换行符等。 ③ 不推荐使用反引号捕获命令输出。你现在应该改用$(...)
猜你喜欢
  • 2018-05-10
  • 2020-02-10
  • 2021-03-30
  • 2017-06-03
  • 2017-11-29
  • 1970-01-01
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多