我坚持使用bash scipt,它应该写入stdout和文件。我正在使用函数和其中的一些变量。每当我尝试将函数重定向到文件并使用tee在屏幕上打印时,我无法使用我在函数中使用的变量,因此它们会以某种方式变为本地。 这是一个简单的例子:
#!/bin/bash
LOGV=/root/log
function var()
{
echo -e "Please, insert VAR value:\n"
read -re VAR
}
var 2>&1 | tee $LOGV
echo "This is VAR:$VAR"
输出:
[root@testbox ~]# ./var.sh
Please, insert VAR value:
foo
This is VAR:
[root@testbox ~]#
提前致谢!
修改
回应@Etan Reisner建议使用
var 2>&1 > >(tee $LOGV)
这种结构的唯一问题是日志文件不能接收所有内容......
[root@testbox~]# ./var.sh
Please, insert VAR value:
foo
This is VAR:foo
[root@testbox ~]# cat log
Please, insert VAR value:
答案 0 :(得分:4)
这是BashFAQ #24的变体。
var 2>&1 | tee $LOGV
...像任何shell管道一样,可以选择在子进程中运行函数var
- 实际上,它在bash中以这种方式运行。 (POSIX sh规范留下了哪些管道组件(如果有的话)在未定义的父shell内运行的详细信息。)
避免这种情况就像不使用管道一样简单。
var > >(tee "$LOGV") 2>&1
...使用进程替换(bash采用的ksh扩展,POSIX sh中不存在)通过文件名(在现代Linux上的tee
形式)表示/dev/fd/##
子进程,输出可以重定向到不将函数移动到管道中。
如果要确保在其他命令运行之前退出tee
,请使用锁定:
#!/bin/bash
logv=/tmp/log
collect_var() {
echo "value for var:"
read -re var
}
collect_var > >(logv="$logv" flock "$logv" -c 'exec tee "$logv"') 2>&1
flock "$logv" -c true # wait for tee to exit
echo "This is var: $var"
顺便说一下,如果你想以这种方式运行多个命令并输出输出,你应该只调用tee
一次,然后根据需要输入它:
#!/bin/bash
logv=/tmp/log
collect_var() { echo "value for var:"; read -re var; }
exec 3> >(logv="$logv" flock "$logv" -c 'exec tee "$logv"') # open output to log
collect_var >&3 2>&3 # run function, sending stdout/stderr to log
echo "This is var: $var" >&3 # ...and optionally run other commands the same way
exec 3>&- # close output
flock "$logv" -c true # ...and wait for tee to finish flushing and exit.