我有一个 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
,您可以使用以下行:
exec &>/dev/null
这将从该点开始将 all
stdout
和 stderr
定向到 /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.
我找到了另一种解决方案,但与paxdiablo的answer相比,我觉得它很笨拙:
if tty -s; then
REDIRECT=/dev/stdout
else
REDIRECT=/dev/null
fi
echo "Normal output" &> $REDIRECT
您可以使用一个函数:
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
这对我来说效果很好。如果
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}
最简单的解决方案是使用 eval (一个 shell 内置函数),因为它将作用于扩展变量中的重定向...并且还作用于命令行中的其他任何内容,因此根据需要添加额外的引号(注意额外的单引号)由于“?”,在下面的 echo 字符串周围添加了引号,否则会导致尝试扩展 shell 文件名)。
#!/bin/bash
# conditional-redirect.sh
if tty -s; then
REDIRECT=
else
REDIRECT=">& /dev/null"
fi
eval echo '"is this visible?"' $REDIRECT