Bash:根据标志重定向到screen或/dev/null

Bash:根据标志重定向到screen或/dev/null,bash,dev-null,Bash,Dev Null,我正试图想出一个方法脚本,在bash中传递一个静默标志,这样所有的输出都将被定向到/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 # N

我正试图想出一个方法脚本,在bash中传递一个静默标志,这样所有的输出都将被定向到
/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
):

显然,
out\u var
行不起作用,但它们给出了我想要的想法:一种将
command1
command2
的输出定向到屏幕或
/dev/null
的方法,具体取决于
-s
是否存在


如何执行此操作?

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

因此,
-s
标志可以通过以下方式处理:

if [[ "$1" == "-s" ]] ; then
    exec >/dev/null 2>&1
fi
# 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
以下完整脚本演示了如何执行此操作:

#!/bin/bash

echo XYZZY

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

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

如果在没有
-s
的情况下运行它,则会得到两行

before和after
echo
语句显示
exec
正在按所述操作,只是更改当前程序的重定向,而不是尝试重新执行它



另一方面,我假设您的意思是“到屏幕”是“到当前标准输出”,它可能是也可能不是实际的终端设备(例如,如果它已经被重定向到其他地方)。如果您确实想要实际的终端设备,它仍然可以完成(例如使用
/dev/tty
),但这将是一个不寻常的要求;我不会尝试猜测,因为您没有发布任何实际输出或错误

但是,有两件事可以帮助您:

  • 你需要弄清楚你的产出到底往哪里去了。标准输出和标准错误是两个不同的东西,重定向其中一个并不一定重定向另一个

  • 在Bash中,您可以将输出发送到/dev/stdout或/dev/stderr,因此您可能需要尝试以下操作:

    if [[ "$1" == "-s" ]] ; then
        exec >/dev/null 2>&1
    fi
    
    # 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
    
  • 将标准错误重定向到标准输出,然后将标准输出发送到/dev/null。这里的秩序很重要

    cmd 2>&1 > /dev/null
    

  • 您的脚本可能也存在其他问题,但对于GNUBash问题,手册是规范的信息源。希望有帮助

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

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

    确保使用双引号,以便在
    eval
    计算变量之前替换该变量。

    在您的情况下,只需将
    out\u var=“to screen”
    更改为
    out\u var=“/dev/tty”
    。并像这样使用它
    command1>$out\u 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
    
    # 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
    
    当然,您也可以通过cli选项设置调试模式,请参阅

    您可以有多个调试或详细级别,如下所示

    # 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
    
    # 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
    

    shell分配中的
    =
    周围没有空格。也就是说,如果您将
    “to screen”
    替换为
    /dev/stdout
    ,并在重定向中使用
    $out\u var
    ,那么假设您想要默认的标准输出位置,我相信您的脚本应该可以正常工作。这也是一本有趣的书。很棒的小贴士@EtanReisner!我提供了另一种观点,但我认为
    exec
    是执行OP的正确方式。然而,在较长的脚本中,exec可能会对管道产生令人惊讶的后果,或者希望将输出发送回原始接收器。回答得好!