如何在不"等待"生成的可执行文件返回的情况下将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
如图所示。