如何让Bash将变量的内容解释为I / O重定向,而不是简单地将这些内容传递给正在执行的命令。以此脚本为例:
#!/bin/bash
test "$1" == '--log' && LOGGING="2>&1 | tee time.log" || LOGGING=""
date $LOGGING
所需的行为是当我使用--log选项运行此脚本时bash将执行
$ date 2>& 1 | tee time.log
如果我没有指定--log,那么它只是输出日期而不创建日志。相反,它将$ LOGGING的内容作为CLI参数传递给日期,从而导致错误:
date: extra operand `|' Try `date --help' for more information.
如果没有像
这样的东西,有没有办法做到这一点#!/bin/bash
test "$1" == '--log' && date 2>&1 | tee time.log || date
实际的应用程序显然要比调用“date”复杂得多,所以我想避免在if else中复制和粘贴该命令两次只是为了附加重定向和日志记录命令。
答案 0 :(得分:2)
如果您的脚本相当长并且您希望在传入--log时记录所有stdout和stderr,我建议使用exec重定向所有内容。看到这篇优秀的文章:
http://www.linuxjournal.com/content/bash-redirections-using-exec
#!/bin/bash
if [[ "$1" == '--log' ]]; then
npipe=/tmp/$$.tmp
trap "rm -f $npipe" EXIT
mknod $npipe p
tee <$npipe log &
exec 1>&-
exec 1>$npipe
fi
date
# and any other commands after this will be logged too.
这种方法的有趣之处在于,您还可以使用perl或gawk或其他一些实用程序为所有记录的行添加时间戳:
#!/bin/bash
if [[ "$1" == '--log' ]]; then
npipe=/tmp/$$.tmp
trap "rm -f $npipe" EXIT
mknod $npipe p
perl -pne 'print scalar(localtime()), " ";' < $npipe | tee time.log &
exec 1>&-
exec 1>$npipe 2>&1
fi
echo hello world
echo hello world 2
运行此命令后,time.log将包含:
$ cat time.log
Wed Jun 8 13:28:45 2011 hello world
Wed Jun 8 13:28:45 2011 hello world 2
此处的缺点是时间戳也会打印到您的终端。
答案 1 :(得分:1)
您可以使用eval
:
eval date $LOGGING
答案 2 :(得分:1)
问题在于,通过添加command in a variable,您实际上将所有内容都转换为字符串,而不是将其作为Bash关键字。尝试将-x
附加到shebang行:
$ ./test.sh --log
+ test --log == --log
+ LOGGING='2>&1 | tee time.log'
+ date '2>&1' '|' tee time.log
date: extra operand `|'
Try `date --help' for more information.
试试这个:
#!/bin/bash -x
logging() {
if [ "$1" == '--log' ]
then
cat 2>&1 | tee time.log
else
cat
fi
}
date | logging "$1"