如何使用 tee 将 STDOUT 从代码块捕获到块内定义的文件名?

如何使用 tee 将 STDOUT 从代码块捕获到块内定义的文件名?

我想发送标准输出对于脚本块到文件,其名称由块内的变量定义。但是,当我使用球座,看来块外的变量不再存在了。没有球座,变量仍然存在。

脚本:

#!/bin/bash
{
    log="mylog.txt"
    echo log: $log
} |tee $log

echo log: $log

结果:

log: mylog.txt
log:

和不我的日志.txt产生的文件球座

答案1

 #!/bin/bash
 log="mylog.txt"
 {
     echo log: $log
 } |tee $log

管道导致命令列表在子 shell 中执行。由于该变量位于不同的子 shell 中,因此无法向上传递。因此,您必须将变量移至公共上下文中才能正确使用。

答案2

命名管道可以为您工作。只需多做一点工作,您就可以稳健地获得一个,而无需进行设置trap或类似的操作来随后处理文件系统清理 - 您只需事先进行清理即可。

pipe=/tmp/$$pipe log=mylog.txt
mkfifo "$pipe"; exec 3<>"$pipe"
{ rm "$pipe"; tee "$log"; } <&3 >/dev/tty &
pipe=$!; exec >&3 3>&-

那里。从这一刻起,所有脚本的输出都被写入(以前是)正在由后台tee进程读取的命名管道。命名管道的特殊文件已从文件系统中删除,因此以后不需要清理它,唯一保留的对它的引用是分配给脚本的stdouttee的文件描述符stdin

也就是说,至少设置一个可能是明智的trap

trap "kill PIPE $pipe" 0

...只是为了确保tee脚本退出后不会在后台挂起。

如果您遇到缓冲问题 - 我认为这不应该成为问题,因为tee有一条开放线路- 您可以通过/dev/tty拨打电话试试运气。的页面特别在关注的地方对冲了它的赌注 - 它指出 作为一个应用程序可能会在调用后重新调整自己的缓冲区 - 但对于交互比无论如何都更加积极。teestdbufstdbufmanteeteedd

相关内容