Script - Save Running Config to txt file
Run the script and it will format the output, run show commands and output the data into a .txt file.
py
import re
import datetime
import os
import platform
import shutil
import sys
import time
import subprocess
# Define aliases for CRT dialog functions
MsgBox = crt.Dialog.MessageBox
Prompt = crt.Dialog.Prompt
# Define global variables
global g_strConfigToSave
g_strConfigToSave = "running"
global g_strAdditionalArgs
g_strAdditionalArgs = ""
# Get the user's home directory
strHome = os.path.expanduser("~")
global g_strMyDocs
g_strMyDocs = strHome.replace("\\", "/") + "/Documents"
global objTab
objTab = crt.GetScriptTab()
objTab.Screen.Synchronous = True
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def Main():
global g_strConfigToSave
# Check if command-line arguments were provided
if crt.Arguments.Count > 0:
strArg = str(crt.Arguments.GetArg(0)).lower()
else:
strArg = g_strConfigToSave
# Validate the provided argument
if not (strArg == "running" or strArg == "startup"):
MsgBox(
"Unrecognized config type: '" + strArg + "'\r\n" +
"Expected either 'running' or 'startup'.\r\n\r\n" +
"Exiting.")
return
g_strConfigToSave = strArg
global g_strAdditionalArgs
# Check for additional command-line arguments
if crt.Arguments.Count > 1:
for nArgIndex in range(1, crt.Arguments.Count):
strAddArg = str(crt.Arguments.GetArg(nArgIndex))
if g_strAdditionalArgs == "":
g_strAdditionalArgs = strAddArg
else:
g_strAdditionalArgs = "{0} {1}".format(g_strAdditionalArgs, strAddArg)
if not objTab.Session.Connected:
strMessage = "You must first be connected to run this script!"
MsgBox(strMessage)
return
# Detect the shell prompt by getting all the text to the left of the cursor.
strPrompt = GetTextLeftOfCursor()
# Handle cases where no prompt is detected
if len(strPrompt) < 1:
objTab.Screen.Send("\r")
while objTab.Screen.WaitForCursor(1):
objTab.Session.SetStatusText("Waiting for prompt...")
strPrompt = GetTextLeftOfCursor()
if len(strPrompt) < 1:
FlashStatusText("No prompt detected! Press Enter first.")
return
# Check if we're in privileged/enable mode
if strPrompt.rstrip()[-1] != '#':
FlashStatusText("Must 'enable' first!")
return
# Ensure we're not in (config) mode
strHostname = GetHostname()
if "config)" in strPrompt:
FlashStatusText("Not in priv EXEC mode... exiting.")
return
bIsASADevice = False
nColsOrig = crt.Session.Config.GetOption("Cols")
objTab.Session.SetStatusText("Getting term info...")
# Get terminal size information
objTab.Screen.Send("sh term\r")
objTab.Screen.WaitForString("sh term")
while True:
objTab.Screen.WaitForStrings([strPrompt, "Width: ", "Length: ", "Width = ", "--More--", "-- More --", "--more--", "-- more --"])
if objTab.Screen.MatchIndex == 1:
# Found strPrompt. We're done looping
break
elif objTab.Screen.MatchIndex == 2:
# Found "Width: "
nCols = objTab.Screen.ReadString(" columns")
elif objTab.Screen.MatchIndex == 3:
# Found "Length: "
nRows = objTab.Screen.ReadString(" lines")
elif objTab.Screen.MatchIndex == 4:
# Found "Width = ". This means we're on an ASA device
bIsASADevice = True
# Read the number of columns up to the ',' character
nCols = objTab.Screen.ReadString(",")
elif objTab.Screen.MatchIndex > 4:
# This means that anything but the first 4 elements of vWaitFors was seen,
# so we need to press SPACE to continue receiving output.
objTab.Screen.Send(" ")
continue
if bIsASADevice:
# ASA devices appear not to support modifying columns/width, so we'll
# just turn off the pager...
objTab.Session.SetStatusText("Setting term pager 0...")
objTab.Screen.Send("term pager 0\r")
objTab.Screen.WaitForString("term pager 0\r")
objTab.Screen.WaitForString(strPrompt)
objTab.Session.SetStatusText("Getting " + g_strConfigToSave + "-config...")
# Then, we'll run the 'show ...' command...
strCmd = "more system:{0}-config\r".format(g_strConfigToSave)
objTab.Screen.Send(strCmd)
# Also, ASA devices seem to output the config without extraneous data like size, etc.,
# so all we have to do is read up to where the prompt appears...
# First, wait for the command we sent to appear as echoed from the remote...
objTab.Screen.WaitForString(strCmd)
objTab.Screen.WaitForString("\n")
# Now, let's read/capture up to the point where the shell prompt appears...
objTab.Session.SetStatusText("Reading " + g_strConfigToSave + "-config...")
strConfig = objTab.Screen.ReadString(strPrompt)
# Restore the pager, set it to what SecureCRT has as rows...
objTab.Session.SetStatusText("Setting pager back to full rows...")
objTab.Screen.Send("term pager {0}\r".format(objTab.Screen.Rows))
objTab.Screen.WaitForString(strPrompt)
else:
# Cisco 881W, etc. case
objTab.Session.SetStatusText("Setting term len 0...")
if int(nRows) > 0:
objTab.Screen.Send("term len 0\r")
objTab.Screen.WaitForString(strPrompt)
if int(nCols) < 132:
objTab.Session.Config.SetOption("Cols", 132)
objTab.Screen.Send("term width 132\r")
objTab.Screen.WaitForString(strPrompt)
objTab.Session.SetStatusText("Getting " + g_strConfigToSave + "-config...")
# Command will either be 'show running-config' or 'show startup-config'
strCmd = "show " + g_strConfigToSave + "-config"
# Accommodate any additional arguments to the sh startup-config or sh running-config
# that were passed in as arguments to the script
if g_strAdditionalArgs == "":
strCmd += "\r"
else:
strCmd += " " + g_strAdditionalArgs + "\r"
objTab.Screen.Send(strCmd)
if g_strConfigToSave == "running":
objTab.Screen.WaitForStrings(["Current configuration", "Invalid input"])
if objTab.Screen.MatchIndex > 1:
FlashStatusText("Invalid command")
return
nBytes = objTab.Screen.ReadString("\r\n")
elif g_strConfigToSave == "startup":
objTab.Screen.WaitForStrings(["Using", "Invalid input"])
if objTab.Screen.MatchIndex > 1:
FlashStatusText("Invalid command")
return
nBytes = objTab.Screen.ReadString(" out of ")
objTab.Screen.WaitForString("bytes\r\n")
else:
MsgBox("Unknown config type: '" + g_strConfigToSave + "'. Exiting.")
return
strConfig = objTab.Screen.ReadString(strPrompt)
objTab.Session.SetStatusText("Restoring original terminal size...")
objTab.Screen.Send("term len " + nRows + "\r")
objTab.Screen.WaitForString(strPrompt)
objTab.Session.Config.SetOption("Cols", nColsOrig)
objTab.Screen.Send("term width " + nCols + "\r")
objTab.Screen.WaitForString(strPrompt)
objTab.Session.SetStatusText("Saving configuration to local file system...")
strDateTimeTag = datetime.datetime.now().strftime("%Y%m%d_%H%M%S.%f")[:19]
strSessionPath = objTab.Session.Path
strSessionPath = strSessionPath.replace("\\", "/")
objMatch = re.match(r'(.*)[/]([^/]+)$', strSessionPath)
strSessionName = strSessionPath
strSavedConfigsFolder = "Config-Saves/"
if objMatch:
strSavedConfigsFolder += objMatch.group(1)
strSessionName = objMatch.group(2)
if strSavedConfigsFolder[-1] != "/":
strSavedConfigsFolder += "/"
strActualFolder = g_strMyDocs + "/" + strSavedConfigsFolder
if not os.path.exists(strActualFolder):
os.makedirs(strActualFolder)
if strActualFolder[-1] != "/":
strActualFolder += "/"
strActualFilePath = strActualFolder + strSessionName + "_" + objTab.Session.RemoteAddress + "_" + g_strConfigToSave + "-config_" + strDateTimeTag + ".txt"
strFilename = Browse("Choose where to save your " + g_strConfigToSave + "-config", "Save", strActualFilePath, "Text Files (*.txt)|*.txt||")
if strFilename != "":
with open(strFilename, "wb") as objFile:
objFile.write(strConfig)
# If on Windows platform, bring up explorer with the file selected
if sys.platform == "win32":
subprocess.call("explorer /e,/select,\"" + strFilename + "\"")
FlashStatusText("Script Completed")
else:
FlashStatusText("Script Cancelled")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def GetHostname():
strPrompt = GetTextLeftOfCursor()
objMatch = re.match(r'^([0-9a-zA-Z\_\-\.]+)', strPrompt)
if objMatch:
return objMatch.group(1)
else:
FlashStatusText("No match on hostname pattern!")
return
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def GetTextLeftOfCursor():
global objTab
nRow = objTab.Screen.CurrentRow
nCol = objTab.Screen.CurrentColumn - 1
strTextLeftOfCursor = objTab.Screen.Get(nRow, 1, nRow, nCol)
return strTextLeftOfCursor
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def FlashStatusText(strMsg):
global objTab
nShortPause = 200
nLongPause = 400
for i in range(1, 5):
objTab.Session.SetStatusText(strMsg)
crt.Sleep(nLongPause)
objTab.Session.SetStatusText("")
crt.Sleep(nShortPause)
objTab.Session.SetStatusText(strMsg)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def Browse(strMessage, strButtonCaption, strDefaultPath, strFilter):
strPlatform = sys.platform
# Windows version of SecureCRT allows FileOpenDialog to return a path to a file that doesn't yet exist.
# But Linux/Mac versions of FileOpenDialog() require an existing file. So, use the nicer interface in Windows,
# and on Linux/Mac, simply present an input box that will allow for the path to be changed, if desired.
# If you are on Linux/Mac and don't like the default path, simply change the value of the g_strMyDocs variable
# (globally defined) as well as the value of the strSavedConfigsFolder variable defined in Main() above.
if strPlatform == "win32":
return crt.Dialog.FileOpenDialog(strMessage, strButtonCaption, strDefaultPath, strFilter)
else:
return crt.Dialog.Prompt(strMessage, strButtonCaption, strDefaultPath)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main()