xiehuahere 发表于 2011-2-24 15:21:07

【已解决】如何通过 TCPSend() 发送 ctrl+c 给远程终端

本帖最后由 xiehuahere 于 2011-3-11 09:49 编辑

如题。
目前已实现通过在23端口建立socket连接来模拟telnet会话,并远程执行脚本,获取回显显示到Edit控件中。但有些脚本出于某种目的,需要死循环执行,想实现点击“Terminate”按钮发送ctrl+c终止脚本运行。
ctrl+c 是不可见字符,如何发送?
尝试多次未果,特来请教。

easied 发表于 2011-2-26 04:51:58

被控端的所有执行操作都写成函数.
设置一个全局数组,任务队排指令及其参数

使用while 1 循环做_Main,有任务时执行,无任务时空循环.

做一个专门监听端口信息的函数,使用AdlibRegister注册.此函数只接收指令,比如"_复制文件|C:\1|D"
设置一个全局变量,定义一个指定比如收到 "Break",则使此全局变量设置为1
在操作的函数里面,检测这个中断变量,如果要求中断,则Return

xiehuahere 发表于 2011-3-2 19:54:39

谢谢你的回答。
忙了几天,今天才有空上来看一下。
我最后是这样做的:用TCPSend()直接发送 killall 命令杀进程了,因为进程名是固定的形式,“/bin/sh /目录/脚本名”。

manlty 发表于 2011-3-2 20:05:33

这应该很简单啊,死循环脚本里弄一个热键专门执行中止循环。当接收到指定的字符串时,触发这个热键不就行了吗

wsfda 发表于 2011-3-3 13:19:21

学习,学习....

xiehuahere 发表于 2011-3-3 15:44:07

回复 4# manlty

我在远程终端上执行是Linux shell脚本。而且脚本不固定,也可能不是我自己写的。
我的工具只负责把脚本从Windows端上载到Linux端并远程控制执行和终止,不能要求在别人的脚本里专门为我的功能加一些东西。

manlty 发表于 2011-3-5 09:13:52

tcp客户端是你写的吧?里面不可以加一些按照指令模拟键盘操作吗

xiehuahere 发表于 2011-3-5 19:38:50

对,TCP客户端是我写的。客户端在Windows侧,Server端在Linux侧。
我不能改server端的东西。

menfan1 发表于 2011-3-6 12:50:27

能不能把源码发上来看看呢

menfan1 发表于 2011-3-6 12:53:12

server端用C写,client端au3写且TCP,发指令调用相应远程脚本执行,终止运行脚本同理。

ceoguang 发表于 2011-3-8 00:03:50

你搞错对象了
ctrl+c并不是发送到远程,而是发送到telnet的console本身

xiehuahere 发表于 2011-3-8 16:57:06

本帖最后由 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中显示的光标?(文本就插入到光标之后,若在脚本运行过程中不断有回显,点击鼠标使光标位置发生改变,就会使得显示的文本变得混杂)

多谢帮忙!

ceoguang 发表于 2011-3-8 23:21:37

晕,你这是telnet还是ssh啊?

xiehuahere 发表于 2011-3-9 13:21:39

本帖最后由 xiehuahere 于 2011-3-9 13:28 编辑

telnet 啊,23端口主要用于Telnet(远程登录)服务。SSH默认端口貌似是22。
通过在23端口建立socket连接来模拟一个telnet通信。
厄。。。版主有疑问?

ceoguang 发表于 2011-3-9 14:26:28

嗯,我明白了.
如果是这样,你得先去了解telnet长什么样子.
不过,据我所知,linux下control键是写作"^",你可以试试发送:^C
不行的话再试试用vkey的方式.
当然,最好的方法是抓包.
页: [1] 2
查看完整版本: 【已解决】如何通过 TCPSend() 发送 ctrl+c 给远程终端