TCL 脚本 - 执行将文本刷新到我的标准输出



如何在不"等待"生成的可执行文件返回的情况下将exec命令的stdout"刷新"到脚本的stdout

例如,在以下脚本中,我希望git clone输出立即出现在我的脚本上下文中:

#!/usr/bin/tclsh
# git outputs progress of the clone download but it isn't visible in this script's context. How can I flush it? 
exec git clone /path/to/some/repo.git

我猜我需要某种pipe "|"tee以及文件重定向的组合。似乎做不好。

若要立即获取输出,需要将子命令作为管道打开。正确的(不是很明显,我们对此表示歉意(方法是使用这种open |[list …]结构:

set mypipeline [open |[list git clone /path/to/some/repo.git]]
# Now to read it by line; we'll just print it out with a line number to show off
set linenum 0
while {[gets $mypipeline line] >= 0} {
    puts "Line [incr linenum]: $line"
}
# Close the pipe now we're at EOF
close $mypipeline

但是请注意,某些程序(我不知道git是否是一个(在管道中运行时会更改其行为,缓冲其输出,直到它们具有完整的缓冲区值。(这是 C 运行时在输出不是终端时默认工作方式的一部分。如果这是一个问题,则必须使用"预期"运行。这是一个足够大的主题,您应该寻找(并在必要时询问(一个单独的问题;唉,复杂性发生了很大的变化。

还要注意 git 可能会写入其标准错误(如本问题中所述,从 PHP exec(( 函数读取 git push 的输出(,因此您可能需要将标准错误合并到捕获的标准输出中(如exec手册页上的简要记录(。

set output [exec git clone /path/to/some/repo.git 2>@1]
set mypipeline [open |[list git clone /path/to/some/repo.git 2>@1]]
# ...
也可以

执行读/写管道,但要复杂得多。

如果您对TCL程序中的程序输出不感兴趣,也可以使用exec命令的">@"选项将输出重定向到其他位置,即">@stdout"。

exec的工作是捕获命令的输出,所以我认为你不能改变它的缓冲。下面是一个在交互式 tclsh 会话中最好的说明的测试:这两个命令都等到执行过程完成后才返回输出,即使是我明确要求行缓冲的命令

exec sh -c {sleep 2; echo a; sleep 2; echo b; sleep 3; echo c}
exec stdbuf --output=L sh -c {sleep 2; echo a; sleep 2; echo b; sleep 3; echo c}

您必须打开命令的管道,然后逐行读取输出。这将在出现上述命令时打印其输出:

set pipe [open [list "|" sh -c {sleep 2; echo a; sleep 2; echo b; sleep 3; echo c}] r]
while {[gets $pipe line] != -1} {puts $line}
close $pipe

当您说它"在此脚本的上下文中不可见"时,您是什么意思?回想一下,exec捕获输出。默认情况下不打印它。我想知道你是否只是想要

puts [exec git clone /path/to/some/repo.git]

但是,如果您想"实时"查看文本,请打开管道并循环gets如图所示。

最新更新