我想创建一个脚本,当以交互方式调用时,该脚本写入标准输出,但如果从另一个脚本调用并且变量 EVENT_LOGGER 由调用脚本定义,则写入文件 EVENT_LOGGER。
可能有一种简单的方法可以做到这一点,但我就是不知道。我当然可以将这个逻辑添加到生成输出的每个地方:
if [[ -f $EVENT_LOGGER ]]
then
echo "Some message" >> $EVENT_LOGGER
else
echo "Some message"
fi
但这会给脚本增加很多体积。
我希望我可以做这样的事情:
if [[ ! -f $EVENT_LOGGER ]]
then
EVENT_LOGGER = "&1"
fi
那么,所有输出命令将是:
echo "Some message" >> $EVENT_LOGGER
他们会转到文件或标准输出,无论 EVENT_LOGGER 指向哪个。
那行不通。还有另一种方法可以让 $EVENT_LOGGER 解析为标准输出吗?
我在 AIX 7.1 上使用 ksh93
答案1
在许多 Unix 变体上,您可以通过文件名访问标准输出/dev/stdout
,因此:
if [[ -z $EVENT_LOGGER ]]; then
EVENT_LOGGER=/dev/stdout
fi
…
echo >>"$EVENT_LOGGER" 'This is a log message'
不过我不确定它是否可以在 AIX 上使用。看"> /dev/stdout" 的可移植性和Unix 系统没有 /dev/stdin、/dev/stdout 和 /dev/stderr?
或者,将所有日志记录保留到标准输出,并可选择将标准输出重定向到文件。如果您调用exec
不带命令名但带有重定向的内置函数,则会为脚本的其余部分设置重定向。
if [[ -n $EVENT_LOGGER ]]; then
exec >>"$EVENT_LOGGER"
fi
…
echo 'This is a log message'
请注意,脚本调用的程序的输出将转到同一日志文件。如果您不想这样做,请在另一个文件描述符上进行日志记录。
if [[ -n $EVENT_LOGGER ]]; then
exec 3>>"$EVENT_LOGGER"
else
exec 3>&1
fi
…
echo >&3 'This is a log message'
另一种方法是根据需要以不同的方式定义函数。
if [[ -n $EVENT_LOGGER ]]; then
log () {
echo "$*" >>"$EVENT_LOGGER"
}
else
log () {
echo "$*"
}
fi
…
log 'This is a log message'
无论你做什么,我建议使用函数。这样,如果您想更改日志记录的工作方式(例如,记录到终端和文件、添加颜色、使其成为有条件的……),就会容易得多。
一些一般注意事项:
- 该测试
-f
测试文件是否存在。这不是一个好的测试。相反,使用-n
(-z
测试它是否为空)来测试变量是否非空。 =
在变量赋值中,不能在符号周围放置空格。
答案2
你要这个:
$ cat interactive.sh
#!/bin/bash
if [[ -n "$EVENT_LOGGER" ]]; then
exec 1>>"$EVENT_LOGGER"
fi
date
echo "hello world"
神奇之处:exec 1>>"$EVENT_LOGGER"
在脚本运行期间重定向标准输出。
演示:
变量未定义,输出到 stdout
$ bash interactive.sh Sat Jan 6 19:06:02 EST 2018 hello world
变量定义,输出到文件
$ env EVENT_LOGGER="./event.logger" bash interactive.sh $ cat event.logger Sat Jan 6 19:06:13 EST 2018 hello world