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

问题描述 投票:0回答:5

我正在尝试想出一种方法脚本来在 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
行不起作用,但它们给出了我想要的想法:一种将
command1
command2
的输出定向到屏幕或
/dev/null
的方法,具体取决于
-s
是否在场。

我该怎么做?

bash dev-null
5个回答
5
投票

您可以使用裸

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
输出(好吧,从技术上讲,您 do 得到
PLUGH
输出,但它被发送到
/dev/null
位桶)。

如果你运行它没有

-s
,你会得到两条线。

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


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

/dev/tty
),但这将是一个不寻常的要求。


1
投票

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

但是,有一些事情可以提供帮助:

  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 重定向的问题,GNU Bash 手册是规范的信息来源。希望有帮助!


0
投票

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

eval
。例如:

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

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

确保使用双引号,以便在

eval
评估变量之前替换该变量。


0
投票

就您而言,您只需将

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 选项设置调试模式,请参阅如何在 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

0
投票

您可以定义一个函数,无论您是否处于详细模式,该函数都会以不同的方式运行您的命令:

function verboseCommand(){
    if [ $VERBOSE -eq 1 ]
    then
        "$@"
    else
        "$@" > /dev/null
    fi
}

您可以通过将其添加到您要执行的任何命令之前来使用该函数。 例如:

VERBOSE=1
verboseCommand echo hello

会产生输出

hello
,但是

VERBOSE=0
verboseCommand echo hello

不会产生任何输出。

© www.soinside.com 2019 - 2024. All rights reserved.