【问题标题】:Bash: redirect to screen or /dev/null depending on flagBash:根据标志重定向到屏幕或 /dev/null
【发布时间】:2014-10-27 09:47:50
【问题描述】:

我正在尝试提出一种方式脚本来在 bash 中传递 silent 标志,以便所有输出都将被定向到 /dev/null(如果存在)和屏幕(如果存在)不是。

我的脚本的 MWE 是:

#!/bin/bash

# Check if silent flag is on.    
if [ $2 = "-s" ]; then
    echo "Silent mode."
    # Non-working line.
    out_var = "to screen"
else
    echo $1
    # Non-working line.
    out_var = "/dev/null"
fi

command1 > out_var

command2 > out_var

echo "End."

我用两个变量调用脚本,第一个无关紧要,第二个 ($2) 是实际的静默标志 (-s):

./myscript.sh first_variable -s

显然out_var 行不起作用,但它们给出了我想要的想法:一种将command1command2 的输出定向到屏幕或/dev/null 的方法,具体取决于@ 987654331@ 是否在场。

我该怎么做?

【问题讨论】:

  • shell 分配中= 周围没有空格。话虽如此,假设您想要默认的标准输出位置,如果您将"to screen" 替换为/dev/stdout 并在重定向中使用$out_var,我相信您的脚本应该可以正常工作。
  • 伟大的提示@EtanReisner!

标签: bash dev-null


【解决方案1】:

在您的情况下,您只需将out_var = "to screen" 更改为out_var = "/dev/tty"。并像这样使用它command1 > $out_var(请参阅您缺少的'$')

我是这样实现的

# Set debug flag as desired
DEBUG=1
# DEBUG=0

if [ "$DEBUG" -eq "1" ]; then
  OUT='/dev/tty'
else
  OUT='/dev/null'
fi

# actual script use commands like this
command > $OUT 2>&1

# or like this if you need
command 2> $OUT

当然你也可以通过cli选项设置调试模式,见How do I parse command line arguments in Bash?

你可以有多个像这样的调试或详细级别

# Set VERBOSE level as desired
# VERBOSE=0
VERBOSE=1
# VERBOSE=2

VERBOSE1='/dev/null'
VERBOSE2='/dev/null'

if [ "$VERBOSE" -gte 1 ]; then
  VERBOSE1='/dev/tty'
fi

if [ "$VERBOSE" -gte 2 ]; then
  VERBOSE2='/dev/tty'
fi

# actual script use commands like this
command > $VERBOSE1 2>&1

# or like this if you need
command 2> $VERBOSE2

【讨论】:

    【解决方案2】:

    如果您不想重定向脚本的所有输出,可以使用eval。例如:

    $ fd=1
    $ eval "echo hi >$a" >/dev/null
    
    $ fd=2
    $ eval "echo hi >$a" >/dev/null
    hi
    

    确保使用双引号,以便在 eval 评估变量之前替换变量。

    【讨论】:

      【解决方案3】:

      您的脚本可能有很多问题;我不会尝试猜测,因为您没有发布任何实际输出或错误。

      但是,有几件事可以提供帮助:

      1. 您需要弄清楚您的输出的真正去向。标准输出和标准错误是两个不同的东西,重定向一个不一定重定向另一个。

      2. 在 Bash 中,您可以将输出发送到 /dev/stdout/dev/stderr,因此您可能想尝试以下方式:

        # Send standard output to the tty/pty, or wherever stdout is currently going.
        cmd > /dev/stdout
        
        # Do the same thing, but with standard error instead.
        cmd > /dev/stderr
        
      3. 将标准错误重定向到标准输出,然后将标准输出发送到/dev/null。在这里订购很重要。

        cmd 2>&1 > /dev/null
        

      您的脚本也可能存在其他问题,但对于Bash shell redirections 的问题,GNU Bash 手册是规范的信息来源。希望对您有所帮助!

      【讨论】:

        【解决方案4】:

        您可以使用裸exec 命令重定向当前程序而无需启动新程序。

        因此,-s 标志可以使用如下方式处理:

        if [[ "$1" == "-s" ]] ; then
            exec >/dev/null 2>&1
        fi
        

        下面的完整脚本展示了如何做到这一点:

        #!/bin/bash
        
        echo XYZZY
        
        if [[ "$1" == "-s" ]] ; then
            exec >/dev/null 2>&1
        fi
        
        echo PLUGH
        

        如果你使用-s 运行它,你会得到XYZZY 但没有PLUGH 输出(嗯,从技术上讲,你确实 得到PLUGH 输出,但它被发送到/dev/null位桶)。

        如果你运行它没有 -s,你会得到两行。

        echo 之前和之后的语句表明 exec 的行为与描述的一样,只是更改当前程序的重定向而不是尝试重新执行它。


        顺便说一句,我假设您的意思是“到屏幕”是“到当前的标准输出”,它可能是也可能不是实际的终端设备(例如,如果它已经被重定向到其他地方)。如果您确实想要实际的终端设备,它仍然可以完成(例如使用/dev/tty),但这是一个不寻常的要求。

        【讨论】:

        • 我提出了另一种观点,但我认为exec 是选择 OP 的正确方法。然而,在较长的脚本中,exec 可能会对管道产生令人惊讶的后果,或者如果想要将输出发送回原始接收器。好答案!
        猜你喜欢
        • 1970-01-01
        • 2019-10-11
        • 1970-01-01
        • 2017-11-29
        • 1970-01-01
        • 1970-01-01
        • 2020-02-10
        • 2021-03-30
        • 1970-01-01
        相关资源
        最近更新 更多