【已解决】如何通过 TCPSend() 发送 ctrl+c 给远程终端
本帖最后由 xiehuahere 于 2011-3-11 09:49 编辑如题。
目前已实现通过在23端口建立socket连接来模拟telnet会话,并远程执行脚本,获取回显显示到Edit控件中。但有些脚本出于某种目的,需要死循环执行,想实现点击“Terminate”按钮发送ctrl+c终止脚本运行。
ctrl+c 是不可见字符,如何发送?
尝试多次未果,特来请教。 被控端的所有执行操作都写成函数.
设置一个全局数组,任务队排指令及其参数
使用while 1 循环做_Main,有任务时执行,无任务时空循环.
做一个专门监听端口信息的函数,使用AdlibRegister注册.此函数只接收指令,比如"_复制文件|C:\1|D"
设置一个全局变量,定义一个指定比如收到 "Break",则使此全局变量设置为1
在操作的函数里面,检测这个中断变量,如果要求中断,则Return 谢谢你的回答。
忙了几天,今天才有空上来看一下。
我最后是这样做的:用TCPSend()直接发送 killall 命令杀进程了,因为进程名是固定的形式,“/bin/sh /目录/脚本名”。 这应该很简单啊,死循环脚本里弄一个热键专门执行中止循环。当接收到指定的字符串时,触发这个热键不就行了吗 学习,学习.... 回复 4# manlty
我在远程终端上执行是Linux shell脚本。而且脚本不固定,也可能不是我自己写的。
我的工具只负责把脚本从Windows端上载到Linux端并远程控制执行和终止,不能要求在别人的脚本里专门为我的功能加一些东西。 tcp客户端是你写的吧?里面不可以加一些按照指令模拟键盘操作吗 对,TCP客户端是我写的。客户端在Windows侧,Server端在Linux侧。
我不能改server端的东西。 能不能把源码发上来看看呢 server端用C写,client端au3写且TCP,发指令调用相应远程脚本执行,终止运行脚本同理。 你搞错对象了
ctrl+c并不是发送到远程,而是发送到telnet的console本身 本帖最后由 xiehuahere 于 2011-3-8 17:04 编辑
源码有点长,请大家继续帮忙,谢谢 ;-)#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <FTPEx.au3>
Opt("GUIOnEventMode", 1)
Const $user = "root", $passwd = ""
Global $host = "", $socket = "", $port = 23 ;Default port for Telnet
Global $filename = "", $isRunning = 0
Dim $width = 398, $height = 486
#Region ### START Koda GUI section ###
$Form1 = GUICreate("Firmware Script Proxy", $width, $height, (@DesktopWidth - $width) / 2, (@DesktopHeight - $height) / 2, $WS_CAPTION)
$Edit1 = GUICtrlCreateEdit("", 8, 8, 377, 385, BitOR($ES_AUTOVSCROLL,$ES_AUTOHSCROLL,$ES_READONLY,$ES_WANTRETURN,$WS_HSCROLL,$WS_VSCROLL,$WS_BORDER))
GUICtrlSetData(-1, '1. Make sure that device is connected and powered on.' & @CRLF _
& '2. Select a script file on local computer.' & @CRLF _
& '3. Click "Execute" button to upload it to device and run remotely.')
$Edit2 = GUICtrlCreateEdit("", 16, 407, 281, 24, BitOR($ES_AUTOVSCROLL,$ES_AUTOHSCROLL))
$Button1 = GUICtrlCreateButton("Browse...", 312, 405, 65, 28)
GUICtrlSetOnEvent(-1, "OpenFile")
$Button2 = GUICtrlCreateButton("Execute", 16, 442, 161, 33, $WS_GROUP)
GUICtrlSetOnEvent(-1, "ExecuteScript")
$Button3 = GUICtrlCreateButton("Terminate", 209, 442, 73, 33, $WS_GROUP)
GUICtrlSetOnEvent(-1, "TerminateScript")
GUICtrlSetState(-1, $GUI_DISABLE)
$Button4 = GUICtrlCreateButton("Exit", 307, 442, 73, 33)
GUICtrlSetOnEvent(-1, "ExitEvent")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
While 1
Sleep(10)
WEnd
Func OpenFile()
$var = FileOpenDialog("Open", "", "Shell Scripts (*.*)", 1, '', $Form1)
If @error Then
;MsgBox(4096, "Warning", "No File is chosen!")
Else
;MsgBox(4096, "", $var)
GUICtrlSetData($Edit2, $var)
EndIf
EndFunc ;==>OpenFile
Func ExecuteScript()
control_state_running_script()
;Check if a script file is selected
$filepath = GUICtrlRead($Edit2)
If $filepath = "" Then
MsgBox(48, "Error", "Please select a file first.", Default, $Form1)
control_state_not_running_script()
Return 1
Else
$filename = StringTrimLeft($filepath, StringInStr($filepath, "\", 1, -1))
EndIf
;Check device connection
GUICtrlSetData($Edit1, "Checking connection ...... ")
$host = get_ip()
If $host = "" Then
MsgBox(48, "Error", "device connection not detected!", Default, $Form1)
GUICtrlSetData($Edit1, "Not detected!" & @CRLF, -1)
Return 1
EndIf
GUICtrlSetData($Edit1, "OK" & @CRLF, -1)
;Upload the selected script file to device
GUICtrlSetData($Edit1, "Uploading file to device ...... ", -1)
If ftp_put_file($filepath, "/taurus/" & $filename) Then
MsgBox(48, "Error", "Upload file to device failed!" & @CRLF)
GUICtrlSetData($Edit1, "Fail!" & @CRLF, -1)
control_state_not_running_script()
Return 1
EndIf
GUICtrlSetData($Edit1, "OK" & @CRLF & @CRLF, -1)
GUICtrlSetData($Edit1, "===================== Start Telnet Session=====================" & @CRLF & @CRLF, -1)
TCPStartup()
$socket = TCPConnect($host, $port)
If $socket = -1 Then
MsgBox(48, "Error", "Connection fail!")
TCPShutdown()
control_state_not_running_script()
Return 1
EndIf
$isRunning = 1
$ret = exec_script()
TCPCloseSocket($socket)
TCPShutdown()
$isRunning = 0
control_state_not_running_script()
Return 0
EndFunc ;==>ExecuteFile
Func TerminateScript()
;~ ;Open another telnet session
;~ $sk = TCPConnect($host, $port)
;~ If $sk = -1 Then
;~ MsgBox(48, "Error", "Connection fail!", Default, $Form1)
;~ Return 1
;~ EndIf
;~ TCPSend($sk, 'kill -9 "/bin/sh /taurus/' & $filename & '"' & @CRLF)
;~ ;TCPSend($sk, 'kill -9 $(ps|grep "' & $filename & '"' & "|grep -v grep|awk '{print $1}')" & @CRLF)
;~ wait_cmd_prompt($sk, "#")
;~ TCPCloseSocket($socket)
;~ TCPCloseSocket($sk)
;~ TCPShutdown()
;Terminate the session and the running script will also be terminated
TCPCloseSocket($socket)
TCPShutdown()
$isRunning = 0
control_state_not_running_script()
Return 0
EndFunc ;==>ExecuteFile
Func ExitEvent()
If $isRunning Then
TerminateScript()
EndIf
Exit 0
EndFunc ;==>ExitEvent
;==================================================================
; Description: Give executable property to the script and execute.
; Return value: Result of the execution.
; 0 - Successful
; 1 - Failed
;==================================================================
Func exec_script()
$delay = 300 ; compensates network/internet delays
Sleep($delay)
wait_cmd_prompt($socket, "login")
TCPSend($socket, $user & @CRLF)
Sleep($delay)
If wait_cmd_prompt($socket, "#") Then Return 1
TCPSend($socket, "chmod a+x /taurus/" & $filename & @CRLF)
wait_cmd_prompt($socket, "#")
TCPSend($socket, "/taurus/" & $filename & @CRLF)
wait_cmd_prompt($socket, "#")
;WinSetState($Form1, "", @SW_HIDE)
Return 0
EndFunc
;==================================================================
; Description: Get IP address of device.
; Return value: A string of IP address.
;==================================================================
Func get_ip()
Local $oIP = ""
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration", "WQL")
For $objItem In $colItems
If StringInStr($objItem.Description, "Taurus") > 0 And $objItem.IPAddress <> "" Then
$oIP = $objItem.IPAddress(0)
ExitLoop
EndIf
Next
If $oIP <> "" Then
$oIP = StringTrimRight($oIP, 2) & "11" ; Convert PC IP to device IP
EndIf
;MsgBox(0, "IP Address", $oIP)
Return $oIP
EndFunc
;==================================================================
; Description: Wait for desired output before sending.
; Return value: 0 - Successful
; 1 - Failed
;==================================================================
Func wait_cmd_prompt($sk, $waitStr)
Local $ack, $count=0
If $waitStr = "#" Then
Do
$ack = TCPRecv($sk, 300)
GUICtrlSetData($Edit1, $ack, -1)
$ack = StringStripWS($ack, 2)
$count += 1
Sleep(300)
Until StringRight($ack, 1) = "#"
ElseIf $waitStr = "login" Then
Do
$ack = TCPRecv($sk, 300)
GUICtrlSetData($Edit1, $ack, -1)
$count += 1
If $count = 5 Then
MsgBox(48, "Error", 'Wait for prompt "' & $waitStr & '" timeout!' & @CRLF & "Please retry!")
Return 1
EndIf
Sleep(300)
Until StringInStr($ack, $waitStr) > 0
EndIf
Return 0
EndFunc
;==================================================================
; Description: Upload the selected shell script to device.
; Return value: 0 - Successful
; 1 - Failed
;==================================================================
Func ftp_put_file($srcFilePath, $DesFilePath)
$Open = _FTP_Open('myFTP')
$ftpConn = _FTP_Connect($Open, $host, $user, $passwd)
_FTP_FilePut($ftpConn, $srcFilePath, $DesFilePath)
If @error <> 0 Then
_FTP_Close($Open)
Return 1
EndIf
_FTP_Close($Open)
Return 0
EndFunc
Func control_state_running_script()
GUICtrlSetState($Edit2, $GUI_DISABLE)
GUICtrlSetState($Button1, $GUI_DISABLE)
GUICtrlSetState($Button2, $GUI_DISABLE)
GUICtrlSetState($Button3, $GUI_ENABLE)
EndFunc
Func control_state_not_running_script()
GUICtrlSetState($Edit2, $GUI_ENABLE)
GUICtrlSetState($Button1, $GUI_ENABLE)
GUICtrlSetState($Button2, $GUI_ENABLE)
If BitAND(GUICtrlGetState($Button3), $GUI_ENABLE) = $GUI_ENABLE Then GUICtrlSetState($Button3, $GUI_DISABLE)
EndFunc1)如何让脚本正在运行的时候,该工具也能响应“Terminate”与“Exit”按钮?
2)如何去除Edit1中显示的光标?(文本就插入到光标之后,若在脚本运行过程中不断有回显,点击鼠标使光标位置发生改变,就会使得显示的文本变得混杂)
多谢帮忙! 晕,你这是telnet还是ssh啊? 本帖最后由 xiehuahere 于 2011-3-9 13:28 编辑
telnet 啊,23端口主要用于Telnet(远程登录)服务。SSH默认端口貌似是22。
通过在23端口建立socket连接来模拟一个telnet通信。
厄。。。版主有疑问? 嗯,我明白了.
如果是这样,你得先去了解telnet长什么样子.
不过,据我所知,linux下control键是写作"^",你可以试试发送:^C
不行的话再试试用vkey的方式.
当然,最好的方法是抓包.
页:
[1]
2