[英]In bash tee is making function variables local, how do I escape this?
I have stucked with a bash scipt which should write both to stdout and into file. 我坚持使用bash scipt,它应该同时写入stdout和文件。 I'm using functions and some variables inside them. 我正在使用函数和其中的一些变量。 Whenever I try to redirect the function to a file and print on the screen with tee I can't use the variables that I used in function, so they become local somehow. 每当我尝试将函数重定向到文件并使用tee在屏幕上打印时,我都无法使用函数中使用的变量,因此它们会以某种方式变为局部变量。 Here is simple example: 这是简单的示例:
#!/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"
Output: 输出:
[root@testbox ~]# ./var.sh
Please, insert VAR value:
foo
This is VAR:
[root@testbox ~]#
Thanks in advance! 提前致谢!
EDIT: Responding on @Etan Reisner suggestion to use var 2>&1 > >(tee $LOGV)
编辑:响应@Etan Reisner建议使用var 2>&1 > >(tee $LOGV)
The only problem of this construction is that log file dosn't receive everything... 这种构造的唯一问题是日志文件无法接收所有内容...
[root@testbox~]# ./var.sh
Please, insert VAR value:
foo
This is VAR:foo
[root@testbox ~]# cat log
Please, insert VAR value:
This is a variant of BashFAQ #24 . 这是BashFAQ#24的变体。
var 2>&1 | tee $LOGV
...like any shell pipeline, has the option to run the function var
inside a subprocess -- and, in practice, behaves this way in bash. ...像任何Shell管道一样,可以选择在子进程中运行var
函数,并且实际上在bash中具有这种行为。 (The POSIX sh specification leaves the details of which pipeline components, if any, run inside the parent shell undefined). (POSIX sh规范未定义哪些管道组件(如果有)在父外壳程序内部运行的详细信息)。
Avoiding this is as simple as not using a pipeline. 避免这种情况就像不使用管道一样简单。
var > >(tee "$LOGV") 2>&1
...uses process substitution (a ksh extension adopted by bash, not present in POSIX sh) to represent the tee
subprocess through a filename (in the form /dev/fd/##
on modern Linux) which output can be redirected to without moving the function into a pipeline. ...使用进程替换(bash采用的ksh扩展名,在POSIX sh中不存在)通过文件名(在现代Linux上为/dev/fd/##
形式)表示tee
子进程,可以将输出重定向到将功能移动到管道中。
If you want to ensure that tee
exits before other commands run, use a lock: 如果要确保在其他命令运行之前退出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"
Incidentally, if you want to run multiple commands with their output being piped in this way, you should invoke the tee
only once, and feed into it as appropriate: 顺便说一句,如果您要运行多个命令,并且以这种方式将它们的输出通过管道传输,则应该仅调用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.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.