【问题标题】:conditional redirection in bashbash 中的条件重定向
【发布时间】:2012-02-04 02:32:16
【问题描述】:

我有一个 bash 脚本,我希望在没有附加 tty 的情况下运行时保持安静(例如来自 cron)。 我现在正在寻找一种在一行中有条件地将输出重定向到 /dev/null 的方法。 这是我想到的一个示例,但我将在脚本中输出更多命令

#!/bin/bash
# conditional-redirect.sh
if tty -s; then 
  REDIRECT=
else 
  REDIRECT=">& /dev/null"
fi
echo "is this visible?" $REDIRECT

很遗憾,这不起作用:

$ ./conditional-redirect.sh
is this visible?
$ echo "" | ./conditional-redirect.sh 
is this visible? >& /dev/null

我不想做的是复制带有重定向或不带有重定向变体中的所有命令:

if tty -s; then 
  echo "is this visible?"
else 
  echo "is this visible?" >& /dev/null
fi

编辑:

如果该解决方案能够为我提供一种以“安静”模式输出某些内容的方法,那就太好了,例如当确实有问题时,我可能希望得到 cron 的通知。

【问题讨论】:

    标签: bash conditional io-redirection


    【解决方案1】:

    对于bash,您可以使用以下行:

    exec &>/dev/null
    

    这将所有 stdoutstderr 从那时起指向/dev/null。它使用exec 的非参数版本。

    通常情况下,exec xyzzy 之类的内容会将当前进程中的程序替换为新程序,但您可以使用此非参数版本在保留当前程序的同时简单地修改重定向。

    因此,在您的具体情况下,您可以使用以下内容:

    tty -s
    if [[ $? -eq 1 ]] ; then
        exec &>/dev/null
    fi
    

    如果您希望丢弃大部分输出但仍想输出一些内容,您可以创建一个新的文件句柄来执行此操作。比如:

    tty -s
    if [[ $? -eq 1 ]] ; then
      exec 3>&1 &>/dev/null
    else 
      exec 3>&1
    fi
    echo Normal               # won't see this.
    echo Failure >&3          # will see this.
    

    【讨论】:

    • ..但它的缺点是所有输出在“安静”模式下都会丢失;在某些情况下,我实际上想要输出一些东西,即使是在安静模式下;请参阅更新的问题。
    • 好点,@daniel,我的牙齿有点长了,旧习惯很难改掉,但我已经用你喜欢的方式更新了答案。
    • 啊,那样的话我可以重定向到/dev/tty
    • 我想我必须使用[[ $? -eq 1 ]]
    • @theartofrain:你问关于 SO 的另一个问题。这样,每个人都看到它,而不仅仅是我,你就有更多机会得到很好的答案。 FWIW,您可以存储当前句柄:exec 8>&1 9>&2 &>/dev/null,然后再执行exec 1>&8 2>&9 来恢复。
    【解决方案2】:

    我找到了另一个解决方案,但与paxdiablo的answer相比,我觉得它很笨拙:

    if tty -s; then 
      REDIRECT=/dev/tty
    else 
      REDIRECT=/dev/null
    fi
    echo "Normal output" &> $REDIRECT
    

    【讨论】:

    • 这会起作用,但前提是输出没有被重定向。 /dev/tty 总是指您的终端设备,因此,如果您使用 myscript >xyzzy.log 运行脚本,您发送到 /dev/tty 的输出将不会出现在该日志文件中。这可能无关紧要,但这取决于您希望如何使用您的程序。
    • @paxdiablo 你可以使用/dev/stdout 而不是/dev/tty 来解决这个问题
    【解决方案3】:

    你可以使用一个函数:

    function the_code {
        echo "is this visible?"
        # as many code lines as you want
    }
    
    if tty -s; then # or other condition
      the_code
    else 
      the_code >& /dev/null
    fi
    

    【讨论】:

      【解决方案4】:

      这对我很有效。如果DUMP_FILE 为空,则转至标准输出,否则转至文件。它在不使用显式重定向的情况下完成这项工作,而只是使用管道和现有应用程序。

      function stdout_or_file
      {
          local DUMP_FILE=${1:-}
      
          if [ -z "${DUMP_FILE}" ]; then
              cat
          else
              sed -n "w ${DUMP_FILE}"
          fi
      }
      
      function foo()
      {
          local MSG=$1
          echo "info: ${MSG}"
      }
      
      foo "bar" | stdout_or_file ${DUMP_FILE}
      

      当然,你也可以挤成一行

      foo "bar" | if [ -z "${DUMP_FILE}" ]; then cat; else sed -n "w ${DUMP_FILE}"; fi
      

      除了sed -n "w ${DUMP_FILE}" 之外,另一个执行相同操作的命令是dd status=none of=${DUMP_FILE}

      【讨论】:

        猜你喜欢
        • 2012-12-30
        • 2021-10-31
        • 2017-12-19
        • 2012-01-09
        • 2012-01-14
        • 1970-01-01
        • 1970-01-01
        • 2020-10-23
        • 2020-03-22
        相关资源
        最近更新 更多