管道plink实时输出到文本小部件

时间:2014-03-09 19:35:42

标签: tcl plink

我正在尝试使用plink连接服务器,在我的文本小部件中执行命令和'pipe'输出:

set myCommand "echo command | plink.exe -ssh server -pw lucas" 
catch {eval exec cmd.exe $myCommand } res
.text insert end $res
# remote command is not working that's why I'm sending command using echo and I'm executing it in cmd.exe because tcl not recognize echo command

不幸的是,这里没有工作。命令在后台执行,没有任何反应。没有管道进入我的文本小部件。如果捕获的输出将实时传输,那将是很好的。

这就是为什么我试过这个:

http://wiki.tcl.tk/3543

package require Tk
set shell cmd.exe
proc log {text {tags {}}} {
    .output configure -state normal
    .output insert end $text $tags
    .output configure -state disabled
    .output see end
}
proc transmit {} {
    global chan
    log "\$ [.input get]\n" input
    puts $chan [.input get]
    .input delete 0 end
}
proc receive {} {
    global chan
    log [read $chan]
}
entry .input
scrollbar .scroll -orient vertical -command {.output yview}
text .output -state disabled -yscrollcommand {.scroll set}
.output tag configure input -background gray
pack .input -fill x -side bottom
pack .scroll -fill y -side right
pack .output -fill both -expand 1
focus .input
set chan [open |$shell a+]
fconfigure $chan -buffering line -blocking 0
fileevent $chan readable receive
bind .input <Return> transmit

并且它在cygwin下运行,但在我尝试执行命令后包装到.exe后,plink正在打开新的黑色cmd窗口(为什么???),命令正在执行并显示输出。从这个窗口我不能再输出输出了。

1 个答案:

答案 0 :(得分:2)

这里有很多问题。希望这些笔记能帮助你弄清楚该怎么做。


通过cmd.exe执行操作似乎有点过于复杂,只是为了让echo通过管道进入plink.exe工作。我会这样写:

catch { exec plink.exe -ssh server -pw lucas << "command" } res

请注意,就像这样,我们根本不需要使用eval


如果失败了,如果该命令来自用户,并且您需要支持命令shell语法,则可以执行此操作:

set myCommand "echo command | plink.exe -ssh server -pw lucas" 
catch { exec cmd.exe /C $myCommand } res

否则你会遇到与cmd.exe选项解析有关的东西,而这可能不是你想要的! (/C很重要;它告诉cmd.exe“这里有一个命令”。)

请注意,我们仍然在这里避免evaleval对你正在尝试做的事情(几乎)肯定是一个坏主意。


使用包装代码时,问题是另一个问题。问题在于Windows进程每个都使用一个特定的子系统(如果我记得正确的话,它在构建可执行文件时实际上是编译选项)并且包装的wish.execmd.exe使用不同的子系统。跨越子系统边界是非常混乱的,因为操作系统试图提供帮助,并为您分配终端。你不想要的。 (我不记得你是否有直接使用plink.exe的问题,我不能从这里检查,因为完全是错误的平台而没有设置一个方便的VM。)


要在后台运行plink.exe,请按以下方式组装管道:

set myCmd [list plink.exe -ssh server -pw lucas]

set chan [open |$myCmd a+];    # r+ or w+ would work just as well for read/write pipe
fconfigure $chan -buffering none -blocking 0

puts $chan "command"

另外,请注意,在使用fileevent时,您需要注意检测EOF条件并在发生这种情况时关闭管道:

proc receive {} {
    global chan
    log [read $chan]
    if {[eof $chan]} {
        close $chan
    }
}

否则,当管道关闭时,你会在管道上获得无限的事件序列(read将始终产生零长度的结果,因为那里没有任何东西)。

相关问题