我正在尝试使用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
不幸的是,这里没有工作。命令在后台执行,没有任何反应。没有管道进入我的文本小部件。如果捕获的输出将实时传输,那将是很好的。
这就是为什么我试过这个:
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窗口(为什么???),命令正在执行并显示输出。从这个窗口我不能再输出输出了。
答案 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
“这里有一个命令”。)
请注意,我们仍然在这里避免eval
。 eval
对你正在尝试做的事情(几乎)肯定是一个坏主意。
使用包装代码时,问题是另一个问题。问题在于Windows进程每个都使用一个特定的子系统(如果我记得正确的话,它在构建可执行文件时实际上是编译选项)并且包装的wish.exe
和cmd.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
将始终产生零长度的结果,因为那里没有任何东西)。