【问题标题】:TCL script - exec flush the text to my stdoutTCL 脚本 - 执行将文本刷新到我的标准输出
【发布时间】:2016-05-25 16:26:56
【问题描述】:

我怎样才能将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 的组合以及文件重定向。 好像没弄好。

【问题讨论】:

    标签: pipe tcl exec stdout


    【解决方案1】:

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

    【讨论】:

    • 我遇到了麻烦,发现我还需要重定向stderr,即。 exec >@stdout 2>@stderr myprogram
    【解决方案2】:

    要立即获得输出,您需要将子命令作为管道打开。正确的(而不是非常明显,我们对此表示歉意)的方法是使用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 运行时默认工作方式的一部分。)如果这是一个问题,您将不得不使用 Expect 运行。这是一个足够大的话题,您应该寻找(并在必要时询问)一个单独的问题;唉,这在复杂性上是一个相当大的变化。

    另外请注意,git 很可能会写入其标准错误(如本问题中所述,Reading output of git push from PHP exec() function),因此您可能需要将标准错误合并到捕获的标准输出中(如 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]]
    # ...
    

    也可以进行读/写管道,但更复杂。

    【讨论】:

    • 非常棒!谢谢你。不知道为什么默认行为不输出到屏幕......对我来说更有意义。
    【解决方案3】:

    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,如图所示。

    【讨论】:

      猜你喜欢
      • 2019-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多