问题描述
我有一些旨在一起工作的shell脚本。第一个脚本(script1.sh)在子外壳中调用下一个脚本。第二个脚本(script2.sh)需要“返回”某些内容以供第一个脚本使用。我需要在第二个脚本中回显的最后一行。但是,当我以这种方式使用它时,第二个脚本中任何通过echo的输出都不会输出到终端。我希望将第一个和第二个(以及第三个和第四个,...)的所有输出都输出到终端,还要写入日志文件。
script1.sh:
#!/bin/sh
func_one() {
RESULT=$(./script2.sh | tail -1)
echo "RESULT: $RESULT"
}
func_one | tee log_file.log
script2.sh:
#!/bin/sh
echo "Hello"
echo "World!"
尝试1个输出:
$ ./script1.sh
RESULT: World!
$
log_file.log内容:
RESULT: World!
如果我尝试在第二个脚本中重定向输出,那么它将输出到终端,而不是日志文件:
script2.sh:
#!/bin/sh
echo "Hello" >&2
echo "World!" >&2
尝试2次输出:
$ ./script1.sh
Hello
World!
RESULT:
log_file.log内容:
RESULT:
我还尝试在脚本1的同一行上输出到terminal和tee
func_one >&2 | tee log_file.log
但这与第一次尝试的结果相同。
我想将两个输出都输出到终端并写入.log文件:(如果它工作正常)
$ ./script1.sh
Hello
World!
RESULT: World!
$
log_file.log内容:
Hello
World!
RESULT: World!
如何获得此结果?另外,最好不要使用bash,因为我们要在其上运行的一些机器没有bash。
我看过这里: How do I get both STDOUT and STDERR to go to the terminal and a log file? 但这对我来说没有帮助。
解决方法
要使script2.sh的所有输出发送到终端而又不干扰script1.sh的工作,请尝试对script1.sh进行以下修改:
$ cat script1.sh
#!/bin/bash
func_one() {
RESULT=$(./script2.sh | tee >(cat >&2) | tail -1)
echo "RESULT: $RESULT"
}
func_one | tee log_file.log
在这里,第一个tee命令确保所有script2.sh
输出通过stderr出现在终端上。为此,需要进程替换(而这又需要从sh
升级到bash
)。
输出为:
$ ./script1.sh
Hello
World!
RESULT: World!
变化
除了不触摸stderr(您可能希望保留该错误)之外,这与上面的相同。在这里,我们创建了一个额外的文件描述符3
,以复制标准输出:
#!/bin/bash
exec 3>&1
func_one() {
RESULT=$(./script2.sh | tee >(cat >&3) | tail -1)
echo "RESULT: $RESULT"
}
func_one | tee log_file.log