我想发送标准输出对于脚本块到文件,其名称由块内的变量定义。但是,当我使用球座,看来块外的变量不再存在了。没有球座,变量仍然存在。
脚本:
#!/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
进程读取的命名管道。命名管道的特殊文件已从文件系统中删除,因此以后不需要清理它,唯一保留的对它的引用是分配给脚本的stdout
和tee
的文件描述符stdin
。
也就是说,至少设置一个可能是明智的trap
:
trap "kill PIPE $pipe" 0
...只是为了确保tee
脚本退出后不会在后台挂起。
如果您遇到缓冲问题 - 我认为这不应该成为问题,因为tee
有一条开放线路- 您可以通过/dev/tty
拨打电话试试运气。的页面特别在关注的地方对冲了它的赌注 - 它指出 作为一个应用程序可能会在调用后重新调整自己的缓冲区 - 但对于交互比无论如何都更加积极。tee
stdbuf
stdbuf
man
tee
tee
dd