VanDyke Software Forums

VanDyke Software Forums (https://forums.vandyke.com/index.php)
-   Scripting (https://forums.vandyke.com/forumdisplay.php?f=14)
-   -   Example: Read Data From Separate Hosts/Commands File And Log To Individual Files (https://forums.vandyke.com/showthread.php?t=10651)

rtb 08-30-2012 05:05 PM

Example: Read Data From Separate Hosts/Commands File And Log To Individual Files
 
6 Attachment(s)
Demonstrates how to connect to hosts read in from a "hosts" file and for each host, send a list of commands read in from a "commands" file. Results of each command run are (by default) logged to separate, uniquely-named files based on the host address and the command that is run. However, the script code is architected to allow you to change this behavior so that it's all logged to one file per host, or even just to a single file.

Download the example scripts:
Python Version (for use on Mac/Linux versions of SecureCRT):
RunCommandsOnMultipleHostsAndLogResults.py.txt
Last updated: 21 May, 2018 (initial revision)

VBScript Version (for use on Windows versions of SecureCRT):
RunCommandsOnMultipleHostsAndLogResults.vbs.txt
Last updated: 21 May, 2018

Example ##hosts.txt and ##commands.txt files:
The following show you the format of what the ##hosts.txt and ##commands.txt files would look like.The ##hosts.txt file can contain host-specific command file directives, which is what the ##DeviceType1Commands.txt and ##DeviceType2Commands.txt files exemplify.



.

Levittown 09-06-2012 04:21 PM

help!
 
Todd:

Also, is there is a way to stop the output from pausing? For instace, if the command output is too long, it will not complte the log file unless I manually press the enter key until the output is completed.

Thank you

Levittown 09-06-2012 05:14 PM

help!
 
Also,

The first host execute the command, but on the second host, I get the following error:

CRT Scripting Runtime error
Error: Sreen.CurrentRow: not connected
Line 186 which points to the following line of code:
nRow = crt.Screen.CurrentRow
:(

miked 09-06-2012 07:26 PM

Quote:

The first host execute the command, but on the second host, I get the following error:

CRT Scripting Runtime error
Error: Sreen.CurrentRow: not connected
Line 186 which points to the following line of code:
nRow = crt.Screen.CurrentRow
SecureCRT is not connected at that point. You need to be connected to the server before using crt.Screen.CurrentRow. I think there's probably much more going on here than we know yet, and should see a log file.

Quote:

Also, is there is a way to stop the output from pausing?
Can you send a SecureCRT raw log file showing the output pausing?

To create a raw log:
  1. Before connecting with the session, select "Raw Log Session" from SecureCRT's "File" menu.
  2. In the "Select Log File" dialog, choose a folder and filename in which you would like the log text to be stored and press the "Save" button. At this point, if you open the "File" menu, you will notice that the "Raw Log Session" menu item now has a check-mark next to it; this indicates that raw logging is activated.
  3. Now connect to the remote machine and perform the actions which cause the reported problem to occur.
  4. Once the problem occurs, disconnect the session and select "Raw Log Session" from the "File" menu to turn off the raw logging feature.
  5. Browse to the location of the raw log file and add the file as an attachment to your e-mail reply.

Levittown 09-08-2012 01:18 PM

I follow your instructions, but the log is empty. I can clearly see that secrteCRT connects to the second host, but it doesnt issue a command, and then I get the error...

Quote:

Originally Posted by miked (Post 37341)
SecureCRT is not connected at that point. You need to be connected to the server before using crt.Screen.CurrentRow. I think there's probably much more going on here than we know yet, and should see a log file.

Can you send a SecureCRT raw log file showing the output pausing?

To create a raw log:
  1. Before connecting with the session, select "Raw Log Session" from SecureCRT's "File" menu.
  2. In the "Select Log File" dialog, choose a folder and filename in which you would like the log text to be stored and press the "Save" button. At this point, if you open the "File" menu, you will notice that the "Raw Log Session" menu item now has a check-mark next to it; this indicates that raw logging is activated.
  3. Now connect to the remote machine and perform the actions which cause the reported problem to occur.
  4. Once the problem occurs, disconnect the session and select "Raw Log Session" from the "File" menu to turn off the raw logging feature.
  5. Browse to the location of the raw log file and add the file as an attachment to your e-mail reply.


joeboy 03-05-2013 02:12 PM

Is there a python version of this example? Thanks!

rtb 03-05-2013 03:02 PM

Hi joeboy,

Thanks for the question. I have one in the works, but it is not yet complete. I will post here when it is.

Elder 03-20-2013 10:50 AM

I second the req for a python version. Well done RTB!

bgagnon 03-20-2013 11:05 AM

Hi Elder,

Todd (RTB) is not available.

I will make sure he knows you "second the motion". :)

rtb 04-24-2013 03:18 PM

Hi All,

I have finally finished my Python port of the VBScript version of this script. Have at it.

quinj 10-10-2013 01:53 PM

Is the Python program will work for Windows 7 too?

bgagnon 10-10-2013 01:58 PM

Hi quinj,

Yes, SecureCRT is capable of hosting "ActiveX Script" engines. Python scripts can be run in SecureCRT/Windows.

quinj 10-10-2013 02:58 PM

I apologize, the python program on this thread can be used in Windows 7. Looking at it inside, it all shows Windows XP.

Thanks
quinj

hvh2000 07-17-2014 04:07 PM

Hi, I'm using this excellent script. I have a noob question - as it is the script saves the configuration files using the IP address in the filename, I am using fqdn's to connect to the devices, so am curious how one would modify it so that the file name reflects what was passed to the script in the hosts.txt file instead of the IP. There may be cases where I use an IP, but if I use an fqdn, I'd prefer the output file to use it as well.

rtb 07-17-2014 04:32 PM

Hi hvh2000,

Thanks for the post. It seems like you are using the VBScript version. If I am wrong, please correct me because the log file code is different between the VBScript and Python versions.

In the VBScript code starting on line 257, the IPADDRESS portion of the template name gets replaced with the IP address (g_objNewTab.Session.RemoteAddress). Line 260 could be modified to use g_strhost which is obtained on line 136 from the host file.

Does this help you accomplish your goal?

hvh2000 07-18-2014 03:51 PM

Hi Todd! I am using the vbs version, and that did the trick! Thanks a lot!

rtb 07-18-2014 04:09 PM

You are welcome hvh2000. I am glad I could help.

hvh2000 08-13-2014 04:09 PM

host prompt changes
 
1 Attachment(s)
Hi Todd,
I ran into a bit of a problem with the vbscript version. I am issuing commands to a (cisco) device, and the script stops when I issue "config term", because the prompt changes from hostname# to hostname(config)#.

How do I modify the script to continue executing commands when the prompt changes from # to config)#?

Adding the current version I'm working with. I added cases for when I need to elevate privileges on a device to be able to work with it. Let me know if I need to clarify anything further.

rtb 08-13-2014 05:07 PM

Hi hvh2000,

There are many ways to accomplish your goal. I know that there is a thread that discusses this exact change. If I can find the thread, I will post it.

The line that needs to be modified in the original script would be 251. Rather than waiting for the prompt, you could wait for all possible prompts. If strPrompt is defined as hostname#, then you could create a new variable by replacing the # with (config)#. For example:
strConfigPrompt = Replace(strPrompt, "#", "(config)#")
The ReadString() call would have multiple strings. For example:
strResult = ReadString(strPrompt, strConfigPrompt)
Does this help?

hvh2000 08-14-2014 09:18 AM

Thanks Todd!! That did the trick!

aluminex 08-16-2014 09:14 AM

Dynamic prompt
 
Todd,

I am trying to do the same thing, but the prompts are much more dynamic. I edited the script and added several prompts, but they literally change with every directory. Any idea how I could alter the script to provide support for dynamic prompts or perhaps trimming everything out except the #.

Thanks

rtb 08-18-2014 10:55 AM

Hi aluminex,

Thanks for the post. The goal is to use something generic enough to work with a wide range of possibilities, but unique enough to prevent false positives.

Is the # symbol unique enough that you the script won't find it in the output of a command that is run?

What types of devices are you connecting to when using the script?

Is it possible to change the shell prompt on the devices?

aluminex 08-19-2014 06:56 AM

Quote:

Originally Posted by rtb (Post 42154)
Hi aluminex,

Thanks for the post. The goal is to use something generic enough to work with a wide range of possibilities, but unique enough to prevent false positives.

Is the # symbol unique enough that you the script won't find it in the output of a command that is run?

What types of devices are you connecting to when using the script?

Is it possible to change the shell prompt on the devices?

Todd,

Thanks for the reply. I am connecting to Fortigate firewalls (FortiOS), and Cisco routers. I think # would be unique enough... not certain though.

rtb 08-19-2014 10:51 AM

Hi aluminex,

Thanks for the update. You will have to run tests, but a simple way to test would be to comment out line 195, and add a line after it that sets strPrompt equal to what you want. For example:
strPrompt = "#"
Does this work for you?

aluminex 08-19-2014 03:27 PM

Works great Todd! Thanks!

rtb 08-19-2014 04:09 PM

Hi aluminex,

Thanks for the update. I am glad to hear that the change is working.

Please remember, that this is a hardcoded string that is not terribly unique. If you get to a point where the script is not functioning as you expect, you may consider looking at the output to ensure that the "#" is not appearing before you expect it to appear (in the prompt).

aaakaundal 09-11-2014 04:23 PM

Hi Todd!!
 
I am trying to use the vbs version of the script but not able to login to devices. I am suspecting that this script is based on ssh login to devices but my devices are only enabled for telnet access only.

Is there any version that uses telnet protocol to login to devices instead of ssh.

rtb 09-11-2014 05:02 PM

Hi aaakaundal,

Thanks for the post.

Actually, if you look at the Connect() function in the VBScript version of the script, you will see on lines 429 to 437 that many different strings are handled. It is anticipated that Telnet connections should work as well.

If you find that there is a response from the remote that isn't handled, you can add the new response and a new case to handle the response.

Does this help?

aaakaundal 10-01-2014 09:06 AM

Quote:

Originally Posted by rtb (Post 42392)
Hi aaakaundal,

Thanks for the post.

Actually, if you look at the Connect() function in the VBScript version of the script, you will see on lines 429 to 437 that many different strings are handled. It is anticipated that Telnet connections should work as well.

If you find that there is a response from the remote that isn't handled, you can add the new response and a new case to handle the response.

Does this help?

I modified below script portion from ssh to telnet and its working.


'
' If you want to authenticate with publickey authentication instead of
' password, in the assignment of strConnectString below, replace:
' " /AUTH password,keyboard-interactive /PASSWORD " & g_strPassword & _
' with:
' " /AUTH publickey /I ""full_path_to_private_key_file"" " & _
strConnectString = _
g_strFirewall & _
" /TELNET " & g_strHost & " 23"

' Call the Connect() function defined below in this script. It handles
' the connection process, returning success/fail.
If Not Connect(strConnectString) Then
strErrors = strErrors & vbcrlf & _
vbtab & "Failed to connect to " & g_strHost & _
": " & g_strError
Else

kgaudineer 10-09-2014 02:58 PM

Example script with Cisco device....
 
I am trying to use the example script (vbs) with a list of IP addreses for all of our Cisco switches. I have been able to get the script to work when using show commands. But now the script is failing when I try to use an tftp command after connecting to the Cisco switch.

What I am trying to do is tftp a copy of the startup config to a backup location.

The command is ....
copy startup-config tftp://tftp server address/folder/file name...

While the command can be entered entirely on a single line the response back from the switch will still require that the return key be pressed 2 more time before the command is executed so I choose to enter the entire command with 3 different line....

1. copy startup-config tftp:{enter}
2. [tftp servers ip address] {enter}
3. [name of file] which is a combo of IP address + strtup.cfg {enter}

The script runs all the way through entering the first command then hangs. I suspect that the response back from the switch is causing the script to hang because it is not he normal # prompt.

After the first command is entered the switch responds back with
address or name of remote host []? (this is where the tftp server IP goes)

but none of the other commands from the command file are entered. Is there a way to continue or should I look at creating a script from scratch ?

rtb 10-09-2014 03:19 PM

Hi kgaudineer,

I don't think that you need a completely new script. I would likely add another condition after line 199. For example:
Code:

If Instr(strCommand, "copy") > 0 Then
    ' Take special action
    ' Perhaps you can build a prompt
    ' Handle the need to press Enter two times
    ' Etc.
Else
    ' Proceed normally with rest of code
End If

Does this help you modify the script to meet your needs?

kgaudineer 10-09-2014 03:58 PM

Good afternoon rtb,

Thank you for the post... Unfortunately that won't help. These are prompts returned by the switch.... I am thinking it may just be easier to create a new script.. I have tried copying and pasting sections of this vbs script into a new one and that hasn't worked out either... My dilemma is there are several hundred of these switches I need to hit and it looks like this script has a hard time with a dynamic prompts....

Just out of curiosity is there any documentation on the commands used in Secure CRT. I downloaded a VBS book and other than the if, then, else, and case.... this book isn't much help for your VBS script. I did see the VBS FAQ but that's not much help either... I am looking for info on the commands and their arguments. For example... objNewTab.Screen.CurrentColumn -1 leaves me with 2 questions.... What is objNewTab and what does the -1 mean?

rtb 10-09-2014 04:26 PM

Hi kgaudineer,
Quote:

I am thinking it may just be easier to create a new script.
It that is the route you want to go, you are welcome to do so. For me, modifying the existing script would be easier.
Quote:

My dilemma is there are several hundred of these switches I need to hit and it looks like this script has a hard time with a dynamic prompts.
The script is not designed to handle prompts dynamically, but you can build that in. There is no reason that you can't call the WaitForScreenContentsToStopChanging() function again to determine what a new prompt would be.

If you manually type the command all at once, what output do you see?

Please post the output exactly as it would appear. If you need to redact sensitive data, replace each redacted character with an "x".
Quote:

Just out of curiosity is there any documentation on the commands used in Secure CRT.
The SecureCRT API is documented in the help file under the Scripting / Script Objects Reference chapter. VBScript is documented by Microsoft, and page one of the scripting manual provides a reference to Microsoft's documentation that does still work.

The scripting manual is a good place to start if you are learning.

The variable objNewTab is an object. The internet has a wealth of information on learning object oriented programming concepts.
Quote:

objNewTab.Screen.CurrentColumn -1
Here is a breakdown of this statement:
  • objNewTab gets a reference to the currently active tab in SecureCRT. This lets us use the script to interact with the tab using the SecureCRT API.
  • Screen is the SecureCRT API object to use.
  • CurrentColumn is a property that is a member of the Screen object. When it is called, it returns the current column of the cursor in the terminal window which is an integer.
  • Using -1 is simply a mathematical operation. If CurrentColumn returned a 9, the result would be 8.

kgaudineer 10-13-2014 11:17 AM

Good Morning RTB thank you for the reply...

to answer the first question these are the promps when trying to ftp the config

In the line below Cisco-2960# is the prompt and copy startup-config tftp: is the command. following the command you must hit return
Ciaco-2960#copy startup-config tftp:

The line in red below is what is returned after hitting the return key. 10.24.21.117 is the IP of the tftpo server. must hit retunr to move on...
Address or name of remote host []? 10.24.21.117

The line below is what is returned after presiing enter. The switch will use its host name as a suggestion for the filename. in all cases we want to keep the host name as the file name and add a .txt to the end of it...
Destination filename [Cisco-2960-confg]?

After pressing enter for the 3 rd time you swill see the output below. this indicates a successful config file transfer.
!!
39344 bytes copied in 0.157 secs (250599 bytes/sec)
Cisco-2960#

The file I am working with I have commented out lines 215 & 216 and 259
Lines 215 & 216 are:
' Wait for the command to be echo'd back to us.
g_objNewTab.Screen.WaitForString strCommand

and Line 259 is:
strResult = g_objNewTab.Screen.ReadString(strPrompt)

The script does look like it will run most of the way through, however are having a problem with the last line feed. There is no more information that needs to be added and all that needs to be done is to just hit the return key. How do we put that as a command in the command file being read in?

Also Is there a way to get one log file for each host instead of one log file for every command that is run? This command file has several lines of commands ...

rtb 10-13-2014 06:11 PM

Hi kgaudineer,

Thanks for the information.

Here is my understanding from what you posted. If you send the command copy startup-config tftp: the Cisco device responds with the following:
Address or name of remote host []? 10.24.21.117
Do you have to manually enter the IP address or is that automatically populated?
After you press Enter, the Cisco device responds with the following:
Destination filename [Cisco-2960-confg]?
Do you just have to press Enter at this point?

kgaudineer 10-13-2014 11:51 PM

Good evening rtb,

following the first command copy startup-config tftp the Cisco switch will respond with:
Address or name of remote host []?
The IP address 10.24.21.117 needs to be manually entered or in this case its just a separate line in my commands file that is read.
After entering the IP address press enter
The switch responds with:
Destination filename [Cisco-2960-confg]?
The switch will automatically use its host name as the config file name. For us this is just fine so there is no need to change anything and we just press the enter key to accept the name as it is shown.

kgaudineer 10-14-2014 09:34 AM

Good morning rtb

I had a second thought this morning... Since there are basically only 3 commands that are being used for this task is there a way to comment out the section of the script that reads commands in from a separate file and just hard code the 3 file transfer steps ? My thoughts are trying it this way...

copy startup-config tftp
10.24.21.117
waitfor string "#", "?" {enter}

OR

copy startup-config tftp://10.24.21.117/{variable to construct file name} {enter}
waitfor string "#", "?" {enter}
waitfor string "#", "?" {enter}

rtb 10-14-2014 09:52 AM

Hi kgaudineer,

It seems like your idea would work. Were you able to successfully edit the script to use your idea?

kgaudineer 10-14-2014 01:38 PM

Good afternoon rtb,

I have not been successful in editing the script yet. Each time I try I break something else with the script....

My plan was to comment out this section starting at line 100....

' Now call the ReadDataFromFile() function for the commands file.
If Not ReadDataFromFile(g_strCommandsFile, _
g_strComment, _
vCommands, _
nCommandCount, _
nCommentLines) Then
DisplayMessage "No commands were found in file: " & vbcrlf & _
vbtab & g_strCommandsFile
Exit Sub
End If

There must be some other dependencies for this section because the error handling and the log file don't work correctly now....

rtb 10-14-2014 05:12 PM

Hi kgaudineer,

There are other dependencies. I am not sure how your script may be different, but in the unmodified script, it is lines 91 to 99 that read in the data from the commands file. The ReadDataFromFile() function definition begins on line 326. You can see that vCommands is an array that is passed by reference when the function is called to read the data from the commands file. After vCommands is populated with the commands to run, it is the foundation of the For Each...Next loop that starts on line 198.

I think that rather than try and get rid of the commands file, it may be easier to add in a little code.

If you were to use the concept that I suggested initially, you could modify the script to handle many different types of commands. The For Each...Next loop would look something like the following:
Code:

For Each strCommand In vCommands
    If strCommand = "" Then Exit For
   
    ' Handle interactive commands.  This could have multiple ElseIf statements.
    ' It would even be possible to include the IP Address in the commands file
    ' and parse it out in the code below.  Commented lines 10-14 and 21 are
    ' related to this possibility.
    If Instr(strCommand, "copy") > 0 Then
        ' Take special action
        ' If the command was of the following format:
        '    copy startup-config tftp, 10.10.10.10
        ' vData = Split(strCommand, ",")
        ' Send the command text to the remote
        ' g_objNewTab.Screen.Send vData[0] & vbcr
        g_objNewTab.Screen.Send strCommand & vbcr

        ' Wait "Address or name of remote host []" step
        g_objNewTab.Screen.WaitForStrings "#", "?"
       
        ' Send the IP address
        ' g_objNewTab.Screen.Send vData[1] & vbcr
        g_objNewTab.Screen.Send "10.10.10.10" & vbcr
       
        ' Wait for "Destination filename [Cisco-2960-confg]" step
        g_objNewTab.Screen.WaitForStrings "#", "?"
       
        ' Press Enter to execute the command
        g_objNewTab.Screen.Send vbcr
       
    Else
        ' Proceed normally with a portion of the code
        ' Send the command text to the remote
        g_objNewTab.Screen.Send strCommand & vbcr

        ' Wait for the command to be echo'd back to us.
        g_objNewTab.Screen.WaitForString strCommand
    End If
       
    ' Since we don't know if we're connecting to a cisco switch or a
    ' linux box or whatever, let's look for either a Carriage Return
    ' (CR) or a Line Feed (LF) character in any order.
    vWaitFors = Array(vbcr, vblf)
    bFoundEOLMarker = False
    Do
        ' Call WaitForStrings, passing in the array of possible
        ' matches.
        g_objNewTab.Screen.WaitForStrings vWaitFors, 1
       
        ' Determine what to do based on what was found)
        Select Case g_objNewTab.Screen.MatchIndex
            Case 0 ' Timed out
                Exit Do
           
            Case 1,2 ' found either CR or LF
                ' Check to see if we've already seen the other
                ' EOL Marker
                If bFoundEOLMarker Then Exit Do
               
                ' If this is the first time we've been through
                ' here, indicate as much, and then loop back up
                ' to the  top and try to find the other EOL
                ' marker.
                bFoundEOLMarker = True
        End Select
    Loop

    ' Now that we know the command has been sent to the remote
    ' system, we'll begin the process of capturing the output of
    ' the command.
   
    Dim strResult
    ' Use the ReadString() method to get the text displayed
    ' while the command was runnning.  Note that the ReadString
    ' usage shown below is not documented properly in SecureCRT
    ' help files included in SecureCRT versions prior to 6.0
    ' Official.  Note also that the ReadString() method captures
    ' escape sequences sent from the remote machine as well as
    ' displayed text.  As mentioned earlier in comments above,
    ' if you want to suppress escape sequences from being
    ' captured, set the Screen.IgnoreEscape property = True.
    strResult = g_objNewTab.Screen.ReadString(strPrompt)
   
    Dim objFile, strLogFile
   
    ' Set the log file name based on the remote host's IP
    ' address and the command we're currently running.  We also
    ' add a  date/timestamp to help make each filename unique
    ' over time.
    strLogFile = Replace( _
        g_strLogFileTemplate, _
        "IPADDRESS", _
        g_objNewTab.Session.RemoteAddress)

    ' Replace any illegal characters that might have been
    ' introduced by the command we're running (e.g. if the
    ' command had a path or a pipe in it)
    strCleanCmd = Replace(strCommand, "/", "[SLASH]")
    strCleanCmd = Replace(strCleanCmd, "\", "[BKSLASH]")
    strCleanCmd = Replace(strCleanCmd, ":", "[COLON]")
    strCleanCmd = Replace(strCleanCmd, "*", "[STAR]")
    strCleanCmd = Replace(strCleanCmd, "?", "[QUESTION]")
    strCleanCmd = Replace(strCleanCmd, """", "[QUOTE]")
    strCleanCmd = Replace(strCleanCmd, "<", "[LT]")
    strCleanCmd = Replace(strCleanCmd, ">", "[GT]")
    strCleanCmd = Replace(strCleanCmd, "|", "[PIPE]")
   
    strLogFile = Replace(strLogFile, "COMMAND", strCleanCmd)
   
    ' Add Time stats to the log file name based on the Template
    ' defined by the script author.
    strLogFile = Replace(strLogFile, "YYYY-", Year(Date) & "-")
    strLogFile = Replace(strLogFile, "-MM-", "-" & NN(Month(Date)) & "-")
    strLogFile = Replace(strLogFile, "-DD-", "-" & NN(Day(Date)) & "-")
    strLogFile = Replace(strLogFile, "-hh'", "-" & NN(Hour(Time)) & "'")
    strLogFile = Replace(strLogFile, "'mm'", "'" & NN(Minute(Time)) & "'")
    strLogFile = Replace(strLogFile, "'ss", "'" & NN(Second(Time)))
                   
    Set objFile = g_fso.OpenTextFile(strLogFile, ForAppending, True)

    ' If you want the command logged along with the results,
    ' uncomment the next two lines
    ' objFile.WriteLine "Results of command """ & strCommand & _
    '    """ sent to host """ & g_strHost & """: "

    ' Write out the results of the command and a separator
    objFile.WriteLine strResult
   
    ' Close the log file
    objFile.Close
Next

There may be additional changes needed, but this is an example of how it would look.

Does this help you move forward in creating your script?


All times are GMT -6. The time now is 01:55 AM.