3

我正在尝试提出一种方式脚本来在 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):

./myscript.sh first_variable -s

显然这些out_var线不起作用,但它们给出了我想要的想法:一种将输出定向command1command2屏幕或/dev/null取决于-s是否存在的方法。

我怎么能这样做?

4

4 回答 4

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输出(好吧,从技术上讲,你确实得到PLUGH了输出,但它被发送到了/dev/null比特桶)。

如果你在没有 -s的情况下运行它,你会得到两条线。

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


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

于 2014-09-03T02:01:45.667 回答
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 手册是规范的信息来源。希望能帮助到你!

于 2014-09-03T02:16:52.040 回答
0

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

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

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

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

于 2014-09-03T02:24:19.477 回答
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
于 2016-10-13T16:20:39.220 回答