susserj Posted May 4, 2011 Posted May 4, 2011 (edited) HiI have written "plink_wrapper.au3" UDF to assist utilizing the command line terminal emulation program know as "plink".For more information about plink and putty see "http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html".The plink_wrapper.au3 UDF contains a few basic functions:_Start_plink($_plink_loc,$_plinkserver); is used to start your terminal session_Plink_close(); is used to close the session_Init_plink_log($_plink_logfile); used to create a log file of the information sent to the screen_Expect($match_text); wait's for text to appear on screen before continuing_Expector($match_text1, $say1, $match_text2, $say2, $match_text3, $say3); performs one of three tasks based on information on screen_Expectlog($match_text); logs text for an individual Expect command; used when main logging is turned off_Say($output); Sends text to screen input_SayPlus($output); Sends text to screen input and a carrage return_Plink_close_logfile($_plink_logfile_handle); closes the log file_Collect_stdout($time); collect _stdout stream for designated period of time_ExpectTimed($match_text,$time); waits for specified time to check for string value in terminal output streamGeneral Comments- This code has been in use for a few months and is not very sophisticated.- When entering your userid and password strings add an extra space at the end.- Finding a valid string to wait for can be tricky. I suggest using putty to record your sessions to find such strings.- New Function _Collect_stdout($time) added 7/10/2011- New Function _ExpectTimed($match_text, $time) added 7/12/2011expandcollapse popup#include-Once ; ==================================================================================================================================== ; Title....................: plink_wrapper ; AutoIt Version...........: 3.3.6.1 ; Language.................: English ; Description..............: UDF Functions to Control "plink.exe" allowing intelligent response to text displayed in terminal sessions ; Author...................: Joel Susser (susserj) ; Last Modified............: 07/12/2011 ; Status:..................: In Production ; Testing Workstation......; WinXP sp3, win7 32bit (It likely works with other versions of Windows but I cannot confirm this right now ) ; Tested Version of Autoit.; Autoit 3.3.6.1 ; What is plink? ;plink is a command line terminal emulation program similar to putty that allows rudimentary scripting. ;Requirements ; Autoit 3.3.6.X ; putty.exe, plink.exe. You can acquire these programs at "http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html". ; Hints ; If you are using the ssh protocol I suggest you connect to your server first ; with putty before you use plink for the first time so that you will not ; be disrupted by the authentication certificate requests. ; When entering your userid and password variables I suggest that you add an ; additional space at the end of these strings. I'm not sure why but if you don't it will likely ; cut off the last letters of your userid and password. ; Figuring out what screen information to wait for before continuing the data input stream ; can sometimes be difficult. I suggest using the putty logging feature to record the text that appears on each screen. ; I beleive it is advisable to do so in small chunks. ; Also, choose strings to recognize that are unique and at the end of the putty screen capture logging sessions ; for each screen. Avoid terminal escape coding. ; ================================================================================================================================ #comments-start Changelog: 6-09-2011 changed example script to use equivalent path with spaces 7-09-2011 added function _Collect_stdout and modified example script 7-12-2011 added function _ExpectTimed and modified example script #comments-end ;#Current List of Functions======================================================================================================= ;_Start_plink($_plink_loc,$_plinkserver) ;_Plink_close() ;_Init_plink_log($_plink_logfile) ;_Expect($match_text) ;_Expector($match_text1, $say1, $match_text2, $say2, $match_text3, $say3) ;_Expectlog($match_text) ;_Say($output) ;_SayPlus($output) ;_Plink_close_logfile($_plink_logfile_handle) ;_Collect_stdout($time) ;_ExpectTimed($match_text, $_plink_timeout) ; =============================================================================================================================== ; #VARIABLES# ==================================================================================================================== global $_plinkhandle="" ; used to handle starting of plink global $_plinkserver="" ; name of server you wish to connect to global $_plink_loc ="" ; location of plink.exe executable on workstation global $_plink_display_messages=false ; display interim messages to screen (default false) global $_plink_display_message_time=1 ; time in seconds messages are displayed global $_plink_logging=false ; record plink log file (default false) global $_plink_logfile="" ; location of plink log file global $_plink_logfile_handle="" ; plink log file handle ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Plink_close ; Description ...: closes plink.exe process ; Author ........: Joel Susser (susserj) ; Syntax.........: $_Plink_close() ; Parameters ....: none required ; example .......: _Plink_close() ; ; Remarks .......: plink.exe should only be running once ; =============================================================================================================================== func _Plink_close() ;If there are any stray plink sessions kill them if ProcessExists("plink.exe") then ProcessClose("plink.exe") Else return false endif EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Start_plink ; Description ...: open a new plink.exe terminal session ; Author ........: Joel Susser (susserj) ; Syntax.........: $_plinkhandle=_Start_plink($_plink_loc, $_plinkserver) ; Parameters ....: $_plink_loc is the location of the plink.exe ececutable on you workstation ; Parameters ....: $_plinkserver is the location of the server you wish to access ; Example........: $_plinkhandle = _Start_plink("c:/putty/plink.exe", "testserver.com") ; Return values .: $plinkhandle, pid of cmd processor ; Remarks........; Currently configured to use ssh protocol ; Remarks .......: Needs to be made more robust ; =============================================================================================================================== ;start the plink session func _Start_plink($_plink_loc,$_plinkserver) _Plink_close(); close any stray plink sessions before starting if $_plink_loc = "" then MsgBox(0, "Error", "Unable to open plink.exe",10) return false Exit endif if $_plinkserver = "" then MsgBox(0, "Error", "Unable to open server",10) Exit return false endif $_plinkhandle = Run(@comspec & " /c" & $_plink_loc & " -ssh " & $_plinkserver,"",@SW_HIDE,7) return $_plinkhandle endFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Init_plink_log ; Description ...: open a new file handle for saving a log file recording your plink terminal session ; Syntax.........: _Init_plink_log($_plink_logfile) ; Parameters ....: $_plink_logfile is the location of the log file ; Example........: _Init_plink_log("c:/putty/plink.log") ; Author ........: Joel Susser (susserj) ; Remarks .......: If the file exists it will be ovewritten (2) ; Remarks........: Initializing the log file does not mean logging gets turned on. ; remarks........; Logging gets turned on with the flag $_plink_logging=true. The default is false ; Remarks........; Sometimes the log files get too long and you just want to log a small section of code see $_Expectlog() ; Remarks........; ; =============================================================================================================================== ;Initialize plink session log file func _Init_plink_log($_plink_logfile) $_plink_logfile_handle = FileOpen($_plink_logfile, 2) ; Check if file opened for writing OK If $_plink_logfile_handle = -1 Then MsgBox(0, "Error", "Unable to open file.") Exit EndIf return true endfunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Expect ; Description ...: Pause until expected text is displayed on output stream of terminal ; Syntax.........: _Expect("text string") ; Parameters ....: one parameter containing a text string. ; Example........: _Expect("Password:") ; Author ........: Joel Susser (susserj) ; Remarks .......: If the flag $_plink_logging is set to true then it will record all the data sent to the output screen ; Remarks........: while it is waiting for the required text to appear. If it runs to long and doesn't find the text this ; remarks........; file can get very big so be careful. ; Remarks........; If the flag $plink_display_message is set to true then it will popup a messages showing you that the text is found. ; Remarks........; I usaully leave the $_plink_display_messages flag on but reduce the time display to 1 second. However, during ; Remards........; development I usually bump it up to 5 seconds. ; =============================================================================================================================== func _Expect($match_text) local $text local $found While 1 $text = StdoutRead($_plinkhandle) if $_plink_logging Then filewriteline($_plink_logfile_handle,"**********************NEW SECTION************************") filewrite($_plink_logfile_handle,$match_text) filewrite($_plink_logfile_handle,$text) filewriteline($_plink_logfile_handle,"**********************END SECTION************************") endif $found = StringRegExp($text,$match_text) If $found = 1 Then If $_plink_display_messages Then MsgBox(4096, $match_text, $text, $_plink_display_message_time) ExitLoop endif sleep(100) Wend EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Expector ; Description ...: Depending on the text that is found in the input stream, perform one of three different tasks ; Syntax.........: _Expector($match_text1, $say1, $match_text2, $say2, $match_text3, $say3) ; Parameters ....: If string in $match_text1 is found then sent the text in $say1 input string ; Parameters ....: If string in $match_text2 is found then sent the text in $say2 input string ; Parameters ....: If string in $match_text3 is found then give the user a popup message and exit script ; Author ........: Joel Susser (susserj) ; Remarks .......: ; Example........: _Expector("Press <Space Bar> to continue", " ", "Do you wish to continue", "y" "Error no data found", "Script shutting down") ; Remarks .......: ; Remarks........: I'm not fully satified with this function. It requires exactly 6 parameters. It should be more fexable to handle ; remarks........; a variable number of parameters. ; Remarks........; Also, it should perhaps have some error handling to check that the parameters it receives are correct. ; Remarks........; Right now when I only need only two choices, not three choices I put dummy data in my second pair of data variables ; Remards........; ; =============================================================================================================================== func _Expector($match_text1, $say1, $match_text2, $say2, $match_text3, $say3) local $text While 1 $text = StdoutRead($_plinkhandle) if $_plink_logging then filewrite($_plink_logfile_handle,"**********************NEW SECTION************************") filewrite($_plink_logfile_handle,"Expector") filewrite($_plink_logfile_handle,$text) filewrite($_plink_logfile_handle,"**********************END SECTION************************") endif If $_plink_display_messages Then MsgBox(4096, $match_text1 & $match_text2, $text, $_plink_display_message_time) sleep(5000) If StringRegExp($text,$match_text3) then MsgBox(4096, "System Error", $say3, 6) ProcessClose("plink.exe") FileClose($_plink_logfile) exit; close program endif If StringRegExp($text,$match_text2) then _Say($say2) ExitLoop Endif If StringRegExp($text,$match_text1) then _Say($say1) ExitLoop Endif sleep(100) Wend EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Expectlog ; Description ...: Similar to _Expect but if forces a logging of the data for a particular search patern in the input stream ; Description ...: Pause until text is displayed on output stream of terminal ; Syntax.........: _Expectlog("text string") ; Parameters ....: one parameter containing a text string. ; Example........: _Epector("Password:") ; Author ........: Joel Susser (susserj) ; Remarks .......: ; Remarks........: As I indicated previously, the log files can get very big. ; remarks........; This function allows targeted logging related to a specific area of your script. ; Remarks........; It is primarily used for debugging. After your script is functional, you will likely convert your _Expectlog ; Remarks........; function calls to _Expect. ; Remards........; ; =============================================================================================================================== func _Expectlog($match_text) local $text local $found While 1 $text = StdoutRead($_plinkhandle) filewrite($_plink_logfile_handle,"**********************" & $match_text & "************************" ) filewrite($_plink_logfile_handle,$match_text) filewrite($_plink_logfile_handle,$text) $found = StringRegExp($text,$match_text) If $found = 1 Then MsgBox(4096, $match_text, $text, 10) ExitLoop endif sleep(100) Wend EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Say ; Description ...: Send the following text string to the input stream of the terminal session ; Syntax.........: _Say("text") ; Parameters ....: Function takes on parameter which contains the text to sent to the input stream. ; Example........: _Say("y") ; Author ........: Joel Susser (susserj) ; Remarks .......: Don't try and say to much at once. Wait for the screen to appear with the prompt for information ; Remards........; This say does not perform a carrage return. If you need a carrage return use _SayPlus ; =============================================================================================================================== ; Say Function func _Say($output) StdinWrite($_plinkhandle, $output) endfunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _SayPlus ; Description ...: Send the following text string to the input stream of the terminal session ; Syntax.........: _SayPlus("text") ; Parameters ....: Function takes on parameter which contains the text to sent to the input stream. ; Example........: _SayPlus("y") ; Author ........: Joel Susser (susserj) ; Remarks .......: Don't try and say to much at once. Wait for the screen to appear with the prompt for information ; Remards........; This type of say performs a carrage return. If you don't need a carrage return use _Say() ; =============================================================================================================================== func _SayPlus($output) StdinWrite($_plinkhandle, $output & @CR) endfunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Plink_close_logfile ; Description ...: close the plink logging file ; Syntax.........: _Plink_close_logfile($_plink_logfile_handle_) ; Parameters ....: $_Plink_close_logfile_handle ; Example........: N/A ; Author ........: Joel Susser (susserj) ; Remarks .......: ; Remards........; ; =============================================================================================================================== ;Close log file func _Plink_close_logfile($_plink_logfile_handle) FileClose($_plink_logfile_handle) endfunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Collect_stdout ; Description ...: Collects text sent to output stream of terminal for specified period of time ; Syntax.........: $variable = _Collect_stdout($time) ; Parameters ....: Function takes one parameter which specifies time(milliseconds) to collect the input buffer. ; Returns........: Returns the contents of stdout collected during specified time interval ; Example........: $output_buffer = $_Collect_stdout(500); 500 is half a second ; Author ........: Joel Susser (susserj) ; ; Remarks........; This function was inspired by comments made by (Phil; justhatched) and jp10558 ; Remarks .......: There are certain situations which can benefit from the ability to collectively parse the stdout stream. ; Remarks........: The potential problem with this approach is that it can sometimes be difficult to predict how long it takes for certain ; remarks........; screens to output their text due to variables such as server load and internet speed etc. ; Remarks........; That being said, with proper testing the time interval can potentially be evaluated for such situations and ; Remarks........; upon potential failure to succeed, the procedure can be repeated. ; Remarks........; See New Sample Script ; ; =============================================================================================================================== Func _Collect_stdout($_plink_timeout) local $text local $sBuffertext local $iBegin = TimerInit() While 1 $text = StdoutRead($_plinkhandle) $sBuffertext = $sBuffertext & $text if $_plink_logging Then filewriteline($_plink_logfile_handle, $text) endif If TimerDiff($iBegin) > $_plink_timeout then ExitLoop endif sleep(100) Wend return $sBuffertext EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _ExpectTimed ; Description ...: Searches for a string in the stdout stream which was collected for a specified period of time ; Syntax.........: $variable = _Epect_timed("string", $time) ; Parameters ....: Function takes two parameters. First is string to find, second is period of in time(milliseconds) to collect the input buffer ; Returns........: Returns the contents of stdout collected during specified time interval ; Example........: $output_buffer = $_Expect__timed("Login:", 5000); 5 seconds ; Author ........: Joel Susser (susserj) ; ; Remarks........; This function was inspired by comments made by (Phil; justhatched) and jp10558 ; Remarks .......: There are certain situations which can benefit from the ability to collectively parse the stdout stream. ; Remarks........: The potential problem with this approach is that it can sometimes be difficult to predict how long it takes for certain ; remarks........; screens to output their text due to variables such as server load and internet speed etc. ; Remarks........; That being said, with proper testing the time interval can potentially be evaluated for such situations and ; Remarks........; upon potential failure to succeed, the procedure can be repeated. ; Remarks........; See New Sample Script ; =============================================================================================================================== Func _ExpectTimed($match_text, $_plink_timeout) local $found local $sBuf_text $sBuf_text = _Collect_stdout($_plink_timeout) $found = StringRegExp($sBuf_text, $match_text) If $found Then If $_plink_display_messages Then MsgBox(4096, $match_text, $sBuf_text, $_plink_display_message_time) return $sBuf_text endif EndFunc ; =============================================================================================================================== ; Sample Script Starts Here============================================================================================================= ; #cs #include plink_wrapper.au3 ;Initialize Variables------------------------------------------------------------------------------------------------------------ $username="admin " ; It seems necessary to put an extra space after the login name. The last character is being cut off. $password="admin1 "; It seems necessary to put an extra space after the password. The last characters is being cut off. $_plink_logging=true ; Turn Logging ON (default is off) $_plink_display_messages=true ; Turn Screen Messages ON (default is on) $_plink_display_message_time=5 ; Display message for 5 secs (default 1 sec) ;-------------------------------------------------------------------------------------------------------------------------------- ; Initizations------------------------------------------------------------------------------------------------------------------- $_plinkhandle=_Start_plink("c:\PROGRA~1\1putty\plink.exe","hostname.com"); Initialized plink connection to server _Init_plink_log("c:\PROGRA~1\putty\plink.log"); Initialize log file. Required even it not being used ;(Special Notes for Windows 7. If you are puttying plink, putty, and plink.log in a subdirectory of "c:\Program Files\" make sure ; you give your user account sufficient rights. Otherwises it may fail to run properly. ; To find the short file name, navigate to directory with cmd console, then type "command". This will show you the short name) ; ------------------------------------------------------------------------------------------------------------------------------- ; Terminal Emulation Session Interaction _Expect("login as:") _SayPlus($username) _Expect("Password:") _SayPlus($password) _Expect("hostname >") _SayPlus("ls") _Expect("hostname >") ;--------Sample Coding to illustrate using _Collect_stdout function----------------- _SayPlus("vncserver") $buf_collect = _Collect_stdout(5000); (5 sec) If StringInStr($buf_collect, "computer:0",1) then ;some function ElseIf StringInStr($buf_collect, "computer:1",1) then ; some function ElseIf StringInStr($buf_collect, "computer:2",1) then ; some function Elseif ... Else MsgBox(0,"Error", "Unable to find required string") Endif ;---------------------------------------------------------------------------------- ;--------Sample Coding to illustrate using _ExpectTimed function ----------------- ; Terminal Emulation Session Interaction $buf_collect = _ExpectTimed("login as:", 1000) if not $buf_collect then MsgBox(4096, "error", "unable to log into server", $_plink_display_message_time) exit Endif _SayPlus($username) _ExpectTimed("Password:", 1000) _SayPlus($password) _ExpectTimed("hostname >", 1000) _SayPlus("ls") _ExpectTimed("hostname >", 1000) ;---------------------------------------------------------------------------------- _SayPlus("exit") ;SHUTDOWN----------------------------------------------------------------------------------------------------------------------- _Plink_close(); shutdown plink session _Plink_close_logfile($_plink_logfile_handle);shutdown log file ; ------------------------------------------------------------------------------------------------------------------------------ #ceIf you have any questions or comments please let me know.Thanks Edited February 2, 2013 by susserj mLipok and zeda 1 1
justhatched Posted June 1, 2011 Posted June 1, 2011 This is really nice and just what I have been looking for! Just a tiny suggestion - escaping/quoting the command string for paths with spaces so it doesn't break - took me a little while to figure out why I had a blank with no errors...Hi I have written "plink_wrapper.au3" UDF to assist utilizing the command line terminal emulation program know as "plink".General Comments- This code has been in use for a few weeks and is not very sophisticated.- When entering your userid and password strings add an extra space at the end.- Finding a valid string to wait for can be tricky. I suggest using putty to record your sessions to find such strings.If you have any questions or comments please let me know.Thanks
justhatched Posted June 6, 2011 Posted June 6, 2011 (edited) Added some tweaks: 2011-06-01 Added escaping of commandline so that if plink is in a dir with spaces it still works, 2011-06-05 Added global timeout const for expect functions so that if the text is not found the calling script can either handle or set an error state(not hang) 2011-06-05 Added return value for _expect and _expectlog functions so that timeout can be trapped, and so that the buffertext can be parsed for other information by the calling script. eg the use case is when the needle text may be found, but the actual text that is required for the calling text may be at different point(s) in the buffer eg scraping a web page or spreadhseet, walking thru some green screens and populating a third system based on green screen data 2011-06-05 Deleted the expector function, as the ability to parse the buffer from the calling script has more flexibilty expandcollapse popup#include-Once ;#include <Constants.au3> ; ==================================================================================================================================== ; Title....................: plink_wrapper ; AutoIt Version...........: 3.3.6.1 ; Language.................: English ; Description..............: UDF Functions to Control "plink.exe" allowing intelligent response to text displayed in terminal sessions ; Author...................: Joel Susser (susserj) ; Last Modified............: 5/6/2011 (Phil; justhatched) ; Status:..................: Alpha ; Testing Workstation......; WinXP sp3, Vista Business (It likely works with other versions of Windows but I cannot confirm this right now ) ; Tested Version of Autoit.; Autoit 3.3.6.1 ; What is plink? ;plink is a command line terminal emulation program similar to putty that allows rudimentary scripting. ;Requirements ; Autoit 3.3.6.X ; putty.exe, plink.exe. You can acquire these programs at "http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html". ; Hints ; If you are using the ssh protocol I suggest you connect to your server first ; with putty before you use plink for the first time so that you will not ; be disrupted by the authentication certificate requests. ; When entering your userid and password variables I suggest that you add an ; additional space at the end of these strings. I'm not sure why but if you don't it will likely ; cut off the last letters of your userid and password. ; Figuring out what screen information to wait for before continuing the data input stream ; can sometimes be difficult. I suggest using the putty logging feature to record the text that appears on each screen. ; I believe it is advisable to do so in small chunks. ; Also, choose strings to recognize that are unique and at the end of the putty screen capture logging sessions ; for each screen. Avoid terminal escape coding. ; ================================================================================================================================ #comments-start Changelog: 4-12-2011 no changes yet 2011-06-01 Added escaping of commandline so that if plink is in a dir with spaces it still works, 2011-06-05 Added global timeout const for expect functions so that if the text is not found the calling script can either handle or set an error state 2011-06-05 Added return value for _expect and _expectlog functions so that timeout can be trapped, and so that the text can be parsed for other information by the calling script. eg the use case is when the text may be found, but the actual text that is required for the calling text may be at a different point in the buffer eg scraping a web page or spreadhseet, walking thru some green screens and populating a third system based on green screen data 2011-06-05 Deleted the expector function, as the ability to parse the buffer from the calling script has more flexibilty #comments-end ;#Current List of Functions======================================================================================================= ;_Start_plink($_plink_loc,$_plinkserver) ;_Plink_close() ;_Init_plink_log($_plink_logfile) ;_Expect($match_text) ;_Expector($match_text1, $say1, $match_text2, $say2, $match_text3, $say3) ;_Expectlog($match_text) ;_Say($output) ;_SayPlus($output) ;_Plink_close_logfile($_plink_logfile_handle) ; =============================================================================================================================== ; #VARIABLES# ==================================================================================================================== global $_plinkhandle="" ; used to handle starting of plink global $_plinkserver="" ; name of server you wish to connect to global $_plink_loc ="" ; location of plink.exe executable on workstation global $_plink_display_messages=false ; display interim messages to screen (default false) global $_plink_display_message_time=1 ; time in seconds messages are displayed global $_plink_logging=false ; record plink log file (default false) global $_plink_logfile="" ; location of plink log file global $_plink_logfile_handle="" ; plink log file handle global Const $_plink_timeout = 5000 ; Global timeout for expect based functions so no hanging.... ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Plink_close ; Description ...: closes plink.exe process ; Author ........: Joel Susser (susserj) ; Syntax.........: $_Plink_close() ; Parameters ....: none required ; example .......: _Plink_close() ; ; Remarks .......: plink.exe should only be running once ; =============================================================================================================================== func _Plink_close() ;If there are any stray plink sessions kill them if ProcessExists("plink.exe") then ProcessClose("plink.exe") Else return false endif EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Start_plink ; Description ...: open a new plink.exe terminal session ; Syntax.........: $_plinkhandle=_Start_plink($_plink_loc, $_plinkserver) ; Parameters ....: $_plink_loc is the location of the plink.exe ececutable on you workstation ; Parameters ....: $_plinkserver is the location of the server you wish to access ; Example........: $_plinkhandle = _Start_plink("c:/putty/plink.exe", "testserver.com") ; ; Author ........: Joel Susser (susserj) ; Return values .: $plinkhandle, pid of cmd processor ; Remarks........; Currently configured to use ssh protocol ; Remarks .......: Needs to be made more robust ; =============================================================================================================================== ;start the plink session func _Start_plink($_plink_loc,$_plinkserver) _Plink_close(); close any stray plink sessions before starting if $_plink_loc = "" then MsgBox(0, "Error", "Unable to open plink.exe",10) return false Exit endif if $_plinkserver = "" then MsgBox(0, "Error", "Unable to open server",10) Exit return false endif $_plinkhandle = Run(@comspec & " /c" & $_plink_loc & " -ssh " & $_plinkserver,"",@SW_HIDE, 7) ; $STDIN_CHILD + $STDOUT_CHILD + $STDERR_CHILD) return $_plinkhandle endFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Init_plink_log ; Description ...: open a new file handle for saving a log file recording your plink terminal session ; Syntax.........: _Init_plink_log($_plink_logfile) ; Parameters ....: $_plink_logfile is the location of the log file ; Example........: _Init_plink_log("c:/putty/plink.log") ; Author ........: Joel Susser (susserj) ; Remarks .......: If the file exists it will be ovewritten (2) ; Remarks........: Initializing the log file does not mean logging gets turned on. ; remarks........; Logging gets turned on with the flag $_plink_logging=true. The default is false ; Remarks........; Sometimes the log files get too long and you just want to log a small section of code see $_Expectlog() ; Remarks........; ; =============================================================================================================================== ;Initialize plink session log file func _Init_plink_log($_plink_logfile) $_plink_logfile_handle = FileOpen($_plink_logfile, 2) ; Check if file opened for writing OK If $_plink_logfile_handle = -1 Then MsgBox(0, "Error", "Unable to open file.") Exit EndIf return true endfunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Expect ; Description ...: Pause until expected text is displayed on output stream of terminal in less than $iTimeout global const ; Syntax.........: _Expect("text string") ; Parameters ....: one parameter containing a text string. ; Returns........: Stdoutread buffer up to the matched text string, else 0 if timed out ; Example........: _Expect("Password:") ; Author ........: Joel Susser (susserj) ; Remarks .......: If the flag $_plink_logging is set to true then it will record all the data sent to the output screen ; Remarks........: while it is waiting for the required text to appear. If it runs to long and doesn't find the text this ; remarks........; file can get very big so be careful. ; Remarks........; If the flag $plink_display_message is set to true then it will popup a messages showing you that the text is found. ; Remarks........; I usaully leave the $_plink_display_messages flag on but reduce the time display to 1 second. However, during ; Remards........; development I usually bump it up to 5 seconds. ; =============================================================================================================================== func _Expect($match_text) local $text local $sBuffertext local $found local $iBegin = TimerInit() While 1 if TimerDiff($iBegin) > $_plink_timeout then return false $text = StdoutRead($_plinkhandle) $sBuffertext = $sBuffertext & $text if $_plink_logging Then filewriteline($_plink_logfile_handle,"**********************NEW SECTION************************") filewrite($_plink_logfile_handle, $match_text) filewrite($_plink_logfile_handle, $text) filewriteline($_plink_logfile_handle,"**********************END SECTION************************") endif $found = StringRegExp($text,$match_text) If $found = 1 Then If $_plink_display_messages Then MsgBox(4096, $match_text, $text, $_plink_display_message_time) ExitLoop endif sleep(100) Wend return $sBuffertext EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Expectlog ; Description ...: Similar to _Expect but if forces a logging of the data for a particular search patern in the input stream ; Description ...: Pause until text is displayed on output stream of terminal ; Syntax.........: _Expectlog("text string") ; Parameters ....: one parameter containing a text string. ; Example........: _Epector("Password:") ; Author ........: Joel Susser (susserj) ; Remarks .......: ; Remarks........: As I indicated previously, the log files can get very big. ; remarks........; This function allows targeted logging related to a specific area of your script. ; Remarks........; It is primarily used for debugging. After your script is functional, you will likely convert your _Expectlog ; Remarks........; function calls to _Expect. ; Remards........; ; =============================================================================================================================== func _Expectlog($match_text) local $text local $sBuffertext local $iBegin = TimerInit() local $found While 1 if TimerDiff($iBegin) > $_plink_timeout then return false $text = StdoutRead($_plinkhandle) $sBuffertext = $sBuffertext & $text filewrite($_plink_logfile_handle,"**********************" & $match_text & "************************" ) filewrite($_plink_logfile_handle,$match_text) filewrite($_plink_logfile_handle,$text) $found = StringRegExp($text,$match_text) If $found = 1 Then MsgBox(4096, $match_text, $text, 10) ExitLoop endif sleep(100) Wend return $sBuffertext EndFunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Say ; Description ...: Send the following text string to the input stream of the terminal session ; Syntax.........: _Say("text") ; Parameters ....: Function takes on parameter which contains the text to sent to the input stream. ; Example........: _Say("y") ; Author ........: Joel Susser (susserj) ; Remarks .......: Don't try and say to much at once. Wait for the screen to appear with the prompt for information ; Remards........; This say does not perform a carrage return. If you need a carrage return use _SayPlus ; =============================================================================================================================== ; Say Function func _Say($output) StdinWrite($_plinkhandle, $output) endfunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _SayPlus ; Description ...: Send the following text string to the input stream of the terminal session ; Syntax.........: _SayPlus("text") ; Parameters ....: Function takes on parameter which contains the text to sent to the input stream. ; Example........: _SayPlus("y") ; Author ........: Joel Susser (susserj) ; Remarks .......: Don't try and say to much at once. Wait for the screen to appear with the prompt for information ; Remards........; This type of say performs a carrage return. If you don't need a carrage return use _Say() ; =============================================================================================================================== func _SayPlus($output) If $_plink_display_messages Then MsgBox(4096, "Output", $output, $_plink_display_message_time) StdinWrite($_plinkhandle, $output & @CR) endfunc ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Plink_close_logfile ; Description ...: close the plink logging file ; Syntax.........: _Plink_close_logfile($_plink_logfile_handle_) ; Parameters ....: $_Plink_close_logfile_handle ; Example........: N/A ; Author ........: Joel Susser (susserj) ; Remarks .......: ; Remards........; ; =============================================================================================================================== ;Close log file func _Plink_close_logfile($_plink_logfile_handle) FileClose($_plink_logfile_handle) endfunc ; =============================================================================================================================== ; Sample Script Starts Here============================================================================================================= ; #cs ;Initialize Variables------------------------------------------------------------------------------------------------------------ $username="admin " ; It seems necessary to put an extra space after the login name. The last character is being cut off. $password="admin1 "; It seems necessary to put an extra space after the password. The last characters is being cut off. $_plink_logging=true ; Turn Logging ON (default is off) $_plink_display_messages=true ; Turn Screen Messages ON (default is on) $_plink_display_message_time=5 ; Display message for 5 secs (default 1 sec) ;-------------------------------------------------------------------------------------------------------------------------------- ; Initizations------------------------------------------------------------------------------------------------------------------- $_plinkhandle=_Start_plink("c:\putty\plink.exe","hostname.com"); Initialized plink connection to server _Init_plink_log("c:\putty\plink.log"); Initialize log file. Required even it not being used ; ------------------------------------------------------------------------------------------------------------------------------- ; Terminal Emulation Session Interaction _Expect("login as:") _SayPlus($username) _Expect("Password:") _SayPlus($password) $buffertext = _Expect("hostname >") if not $buffertext Then ;we have timed out waiting for our string, so failed to login _Plink_close() _Plink_close_logfile($_plink_logfile_handle);shutdown log file Exit Else ;record something about the machine we have logged into, and optionally apply some logic to what is found _SayPlus("ls") _Expect("hostname >") _SayPlus("exit") EndIf ;SHUTDOWN----------------------------------------------------------------------------------------------------------------------- _Plink_close(); shutdown plink session _Plink_close_logfile($_plink_logfile_handle);shutdown log file ; ------------------------------------------------------------------------------------------------------------------------------ #ce Edited June 6, 2011 by justhatched
susserj Posted June 9, 2011 Author Posted June 9, 2011 Hi justhatched I like many of your improvements except the removal of my "_expector" function. My particular terminal sessions require, fairly lengthy, and variable amounts of time to process, which occur at certain places in the script and the terminal application throws lots of output to the screen, which could likely overflow the "$sBuffertext" variable. I liked the rest though. Cheers susserj
justhatched Posted June 9, 2011 Posted June 9, 2011 Thanks susserj, toyed with adding an optional param to the _expect function for a lossy buffer for the same reason, as some scenarios you only need to know it got there, whereas in other scenarios you may need to process the data(eg a list). Was not sure what could generate so much data without asking for it that it would blow up so left it, and it also meant no calling script would fail with param mismatches. The reason I dropped the _Expector function was because it looked like a select case from the calling script would allow a better separation into script vs library, as well as more flexibility. eg you can have as many or few inputs to a select case statement. Horses for courses tho so whatever works best for the one doing the work! This is a nice library for reusing plink functions in all sorts of ways, thanks for putting it up.
hezi Posted June 15, 2011 Posted June 15, 2011 I must say it looks great, very clear and easy. im looking for this functions a long time. trying them right now... Thanks!
jp10558 Posted July 7, 2011 Posted July 7, 2011 So, let's say I want to run a vnc server, specifically running vncserver on the remote Linux computer. I then need to know, from the output, what display it got assigned. I get output like New 'computer:2 (jmp242)' desktop is computer:2 Starting applications specified in /home/jmp242/.vnc/xstartup Log file is /home/jmp242/.vnc/computer:2.log How do I parse for the "2" with this to get what I need?
susserj Posted July 10, 2011 Author Posted July 10, 2011 So, let's say I want to run a vnc server, specifically running vncserver on the remote Linux computer. I then need to know, from the output, what display it got assigned. I get output like New 'computer:2 (jmp242)' desktop is computer:2 Starting applications specified in /home/jmp242/.vnc/xstartup Log file is /home/jmp242/.vnc/computer:2.log How do I parse for the "2" with this to get what I need? Hi I have added a new function to my plink_wrapper.au3 UDF to accommodate this type of situation. The function is called “_Collect_stdout”. Please see my updated coding and sample scripting in my original post. Thanks
jp10558 Posted July 12, 2011 Posted July 12, 2011 (edited) Great- I'm much closer. How do I forward a port over SSH so that I can connect to my VNC server? I tried just running my own plink with command line options: Run("plink " & $username & "@computer -pw " & $password & ' -L 159'& $vnc & ':computer:59'&$vnc,"",@SW_SHOW,0x8) I did not add the spaces for the username + password here, so should work, but it just flashes on the screen and looks like it's immediately exiting . . . Any ideas? Edited July 12, 2011 by jp10558
susserj Posted August 14, 2011 Author Posted August 14, 2011 Great- I'm much closer. How do I forward a port over SSH so that I can connect to my VNC server? I tried just running my own plink with command line options: Run("plink " & $username & "@computer -pw " & $password & ' -L 159'& $vnc & ':computer:59'&$vnc,"",@SW_SHOW,0x8) I did not add the spaces for the username + password here, so should work, but it just flashes on the screen and looks like it's immediately exiting . . . Any ideas? Sorry, this is outside of my area of expertise.
NutCracker Posted October 19, 2011 Posted October 19, 2011 Hi People, I am using plink to obtain the data from a log file on server using the tail command . using the function _start_plink() It is working fine . Only issue is since tail is a never ending command , i use _plink_close() to stop the command. using _ plink_close() also closes my session. Is there any way to maintain the session , like by sending the (CTRL+C) command to the server (same as we do in putty). Thanks!!...
NutCracker Posted October 29, 2011 Posted October 29, 2011 HI, Got the solution myself. The trick is to not close plink . But instead use Stdinwrite($plinkhandle,char(03)) ; sending CTRL +C to the console. Now to pause the the connection to keep the session alive .(Below routine will keep the session alive) while true StdinWrite($_plinkhandle,"date"& @CRLF) $msg = TrayGetMsg() Sleep(1000) Switch $msg Case $end ConsoleWrite("Exiting SSH Pause routine at " & _Now() & @CR) _start_session() Case $ExitItem _plink_close() Exit 0 EndSwitch WEnd It is important to flush the stdout before sending any more command so as to flush out the output generated using the date command which is have used as a dummy command to keep the shell busy. Hope this is useful. Thanks!!
BartW Posted November 1, 2011 Posted November 1, 2011 hi, I modify the _Start_plink Function to send the Username and password when using ssh. and maak the option to use other protecols end poorts. expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name...........: _Start_plink ; Description ...: open a new plink.exe terminal session ; Author ........: Joel Susser (susserj) ; Syntax.........: $_plinkhandle=_Start_plink($_plink_loc, $_plinkserver) ; Parameters ....: $_plink_loc is the location of the plink.exe ececutable on you workstation ; Parameters ....: $_plinkserver is the location of the server you wish to access ; Parameters ....: $_plink_user ; Parameters ....: $_plink_Password ; Parameters ....: $_plink_Conection_Type ; Parameters ....: $_plink_Port ; Example........: $_plinkhandle = _Start_plink("c:/putty/plink.exe", "testserver.com","my name","my password","ssh","5022") ; Return values .: $plinkhandle, pid of cmd processor ; =============================================================================================================================== ;start the plink session func _Start_plink($_plink_loc,$_plinkserver,$_plink_user = "",$_plink_Password= "",$_plink_Conection_Type= "Telnet",$_plink_Port= "23") _Plink_close(); close any stray plink sessions before starting $Protocol = " -telnet " $LogonData = "" if not FileExists($_plink_loc)then MsgBox(0, "Error", "Unable to located plink.exe",10) return false Exit endif if $_plinkserver = "" then MsgBox(0, "Error", "NO server ip ",10) Exit return false endif if $_plink_Conection_Type <> "Telnet" then if $_plink_Conection_Type = "Rlogin" then If $_plink_Port = "23" Then $_plink_Port= "513" $Protocol = " -rlogin " ElseIf $_plink_Conection_Type = "ssh" then If $_plink_Port = "23" Then $_plink_Port= "22" $Protocol = " -ssh " Elseif $_plink_Conection_Type = "serieal" then If $_plink_Port = "23" Then $_plink_Port= "9600" $Protocol = " -serial " ElseIf $_plink_Conection_Type = "Raw" then If $_plink_Port= "" Then MsgBox(0, "Error", "NO server Poort ",10) Exit return false endif $Protocol = " -raw " EndIf endif if not $_plink_user = "" then $LogonData = " -l "&$_plink_user if not $_plink_Password = "" then $LogonData = $LogonData&" -pw "&$_plink_Password EndIf ;Plink.exe -telnet -p 23 host.name -l User.name -pw Password If $Protocol = " -ssh " then ;ssh $_plinkhandle = Run(@comspec & " /c" &$_plink_loc & $Protocol & "-P "&$_plink_Port&" "& $_plinkserver& $LogonData,"",@SW_SHOW,$STDIN_CHILD + $STDOUT_CHILD ) Else; not ssh $_plinkhandle = Run(@comspec & " /c" & $_plink_loc & $Protocol & "-P "&$_plink_Port&" "& $_plinkserver,"",@SW_SHOW,$STDIN_CHILD + $STDOUT_CHILD ) EndIf ProcessWait("Plink.exe");Wait to proses exists return $_plinkhandle endFunc ; ===============================================================================================================================
BartW Posted November 1, 2011 Posted November 1, 2011 I was wondering if we could also embed plink.exe just like the sqlite.dll
NutCracker Posted November 3, 2011 Posted November 3, 2011 Dont know , but you can use FileInstall() to install plink at run time. Thanks..!!
PhmTunV Posted November 23, 2012 Posted November 23, 2012 Hi there! I use plink wrapper to connect to SSH, but found some problem. # include <Plink Wrapper.au3> $ iPID = _Start_plink (@ ScriptDir & ' plink.exe', '192 .168.0.122 ') $ a = _Collect_stdout (3000) MsgBox (0,'', $ a) _Plink_close () With above code, the return value $ a = "login as" at some folder, I can log in with root / alpine, but when I move it to another folder, the return value $ a = '', that means "login as" does not appear and I can not enter a username and password, as well as the implementation of the next command. Please help me. Thank you very much!
SadBunny Posted January 23, 2013 Posted January 23, 2013 (edited) Sorry to resurrect. I was looking for a way to run a remote unix bash script from a Windows domain login (autoit-)script, and get back the output from the bash script and came to this thread by search. Looks nice!But, I could not really use this UDF because it "says" things to the plink session and "waits" for a certain string to appear, even to the point of waiting for user/password prompt. Should not be necessary (is actually quite cumbersome) if you just want to run some remote command on some user@host combination and get its output in a string, as long as your remote machine accepts that kind of direct login, which should be pretty normal. plink.exe supports using username/password (or username/keyfile) direct connect session already, as BartW also demonstrated a couple of posts before.Also, having to manually putty or plink to the server to allow it to push the host ssh key into the registry (to not be disrupted by the auth request - I need a full-auto login script obviously) is not an option for tens to hundreds of very limited and unpredictable office user logins. So for my purposes I proactively write the key of the machine in question to the correct place in the registry (which is in CURRENT_USER-land so should be possible from limited user elevation), so plink.exe will never ask to allow it and just do as it's told. Security note: this is not auto-acceptance of a host-key (which would kinda defeat part of the purpose of ssh), it's pre-configuring the known host key in the registry so plink.exe thinks it was accepted earlier. If that key is wrong/unknown (i.e. fake server in between?), the connect should just gracefully fail. This works well enough (and is secure enough) for our purposes.I just wanted to give username/password/host/command to a function, run the command, and get the output and then quit the session. I imagine others visiting this thread might want this too. It can be easily done in just a few lines of code (though omitting some error checking). This can be easily modified for more customization possibilities (like BartW did) but for most of my cases that won't be needed. The bottom line is that this function is just one function that runs one command and feeds back all standard output that was received from the plink session. Nothing more, nothing less Hope this helps anyone. Feel free to use this in any way you want.Func _runSshCommand($plinkUser, $plinkHost, $command, $password = "", $timeoutInMs = 0) $plinkFile = @UserProfileDir & "\AppData\Local\plink.exe" FileInstall("c:\AU3_dox\plink.exe", $plinkFile, 1) $runThis = @ComSpec & " /c " & $plinkFile & " -batch " & $plinkUser & "@" & $plinkHost If $password <> "" Then $runThis &= " -pw " & $password $runThis &= " " & $command $plinkHandle = Run($runThis, "", @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD + $STDERR_CHILD) $plinkFeedback = "" $waitForOutputStartTime = TimerInit() Do Sleep(10) $plinkFeedback &= StdoutRead($plinkHandle) $stdoutReadError = @error Until $stdoutReadError Or ($timeoutInMs And TimerDiff($waitForOutputStartTime) > $timeoutInMs) If ProcessExists("plink.exe") Then ProcessClose("plink.exe") If $stdoutReadError <> 0 Then Return $plinkFeedback MsgBox(16, "Timeout", "Timeout while waiting for plink command output!") EndFunc ;==>_runSshCommandUsage example:#include <Constants.au3> Global $unixUser = "user" Global $unixPassword = "password" Global $unixHost = "unixhost" Global $unixHostKey = "0x23,0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" _writePuttyKnownHostKeyToRegistry($unixHost, $unixHostKey) $sshCommand = "ls -la /tmp" $answer = _runSshCommand($unixUser, $unixHost, $sshCommand, $unixPassword) If $answer <> "" Then MsgBox(0, "output", $answer) EndIf Exit Func _writePuttyKnownHostKeyToRegistry($host, $hostKey) RegWrite("HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys", "rsa2@22:" & $host, "REG_SZ", $hostKey) EndFunc ;==>_writePuttyKnownHostKeyToRegistryNote: to learn what unixHostKey cache entry to write to the registry on machines that have not connected to the unix box before (thus preventing the interactive 'store this key in cache' prompt from plink), do one manual session from your own machine, allow it to store the key, then look in HKEY_CURRENT_USERSoftwareSimonTathamPuTTYSshHostKeys and just copypaste the whole thing into the RegWrite function call. Edited January 26, 2013 by SadBunny Roses are FF0000, violets are 0000FF... All my base are belong to you.
ali980 Posted June 27, 2013 Posted June 27, 2013 (edited) Thank you very much . The "plink_wrapper.au3" UDF help me a lot to hide and automate everything in the background. Edited June 27, 2013 by ali980
Ajster1989 Posted July 5, 2013 Posted July 5, 2013 Ok so I'm completely new to plink, I understand putty enough to use it for what I need. Here is what I am attempting hopefully I can get some help. I am using putty to test a device on a serial connection. I run commands and it tests the devices buttons, boards, and so on. then gives me a pass/fail. I want to make a wrapper with this by executing predefined scripts and having my program monitor the output back (the pass/fail results). I figured out how to launch putty from a script with the settings I need but can't figure out how to get plink to do the same thing. The putty website isn't descriptive enough to help. Is this the tool that would do what I need it to do. Any help would be much appreciated!!! Thanks!
setengahgila Posted July 5, 2013 Posted July 5, 2013 how to connect ssh server via specified proxy:port??
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now