在bash tee中,使函数变量成为局部变量,我该如何转义? [英] In bash tee is making function variables local, how do I escape this?

查看:49
本文介绍了在bash tee中,使函数变量成为局部变量,我该如何转义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我坚持使用bash scipt,它应该同时写入stdout和文件.我正在使用函数和其中的一些变量.每当我尝试将函数重定向到文件并使用tee在屏幕上打印时,我都无法使用函数中使用的变量,因此它们会以某种方式变为局部变量.这是简单的示例:

I have stucked with a bash scipt which should write both to stdout and into file. 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. 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"

输出:

[root@testbox ~]# ./var.sh   
Please, insert VAR value:

foo
This is VAR:
[root@testbox ~]#

提前谢谢!

回应@Etan Reisner建议使用 var 2>& 1>>(tee $ LOGV)

Responding on @Etan Reisner suggestion to use 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:

推荐答案

这是 BashFAQ#24的变体.

var 2>&1 | tee $LOGV

......像任何shell管道一样,可以选择在子进程中运行功能 var ,并且实际上在bash中表现为这种方式.(POSIX sh规范保留了未定义哪些管道组件(如果有的话)在父外壳程序内部运行的详细信息.)

...like any shell pipeline, has the option to run the function var inside a subprocess -- and, in practice, behaves this way in bash. (The POSIX sh specification leaves the details of which pipeline components, if any, run inside the parent shell undefined).

避免这种情况就像不使用管道一样简单.

Avoiding this is as simple as not using a pipeline.

var > >(tee "$LOGV") 2>&1

...使用进程替换(bash采用的ksh扩展,在POSIX sh中不存在)通过文件名表示 tee 子进程(格式为/dev/fd/## (在现代Linux上),该输出可以重定向到该函数,而无需将该函数移入管道.

...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.

如果要确保在其他命令运行之前退出 tee ,请使用锁:

If you want to ensure that tee exits before other commands run, use a lock:

#!/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 ,并根据需要将其输入:


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:

#!/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.

这篇关于在bash tee中,使函数变量成为局部变量,我该如何转义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆