Running standard IOS backup scripts on your shiny new Catalyst 1300 switches only to hit walls with truncated outputs or command mismatches? You’re not alone—these industrial Ethernet beasts (IE-1300 series) run a streamlined IOS-XE variant with tweaks that break old playbooks. Forget terminal length 0
for pagination; it demands terminal datadump
to unleash full show running-config
flows. Interface syntax? Version pulls? Clock syncs? All subtly shifted, turning generic scripts into frustration fests.
Enter this guide: a battle-tested Paramiko script dialed in for C1300 quirks, pulling show running-config
, show interfaces status
, show version
, and show clock
into bundled, timestamped files (e.g., 192_168_1_10_20251016.txt
). No more manual SSH marathons—automate audits that actually work on your next-gen gear. If you’re migrating from classic IOS catalysts, this is your upgrade path to reliable auto-backups. Let’s script the future.
Why This Matters for Catalyst 1300 Owners
Traditional IOS automation shines on Catalyst 2960s or 9300s, but the 1300’s lightweight IOS-XE (like v4.1.6.54) introduces syntax variances: pagination killers like “More:” prompts ignore length tweaks, and outputs need datadump to flow freely. Result? Scripts grab 1% of configs, leaving you blind to port states or firmware details. This tailored approach fixes that—full captures for compliance, troubleshooting, or baseline logging. Scale it across your access/industrial edges, and reclaim hours from CLI drudgery.
Prerequisites
- Python 3.x: Fresh install if you’re starting.
- Paramiko: Hit
pip install paramiko
for SSH muscle. - SSH Access: Privileged logins (no enable mode—verify:
show run
spits full output on connect). - IP Inventory:
access_switch.txt
with IPs, one per line. - Output Folder: Script auto-makes D:\python\ for your audit dumps.
Security Callout: Hardcode creds for PoCs only—migrate to env vars or HashiCorp Vault for real deployments.
The Script: C1300-Optimized Audit Engine
Save as cisco_1300_audit_datadump.py
. It’s built from the ground up for 1300 syntax, chaining commands with datadump to ensure complete pulls.
import paramiko
import sys
import time
import os
from datetime import datetime # For timestamped filenames
# HARDCODED CREDENTIALS - REPLACE WITH YOURS (SECURE IN PROD)
username = 'your_username' # e.g., 'admin'
password = 'your_password' # e.g., 'cisco123'
# Path to TXT file with switch IPs (one per line)
ips_file_path = r'C:\path\to\your\access_switch.txt' # Adjust for your OS
# Local backup directory - creates if missing
backup_dir = r'D:\python'
os.makedirs(backup_dir, exist_ok=True)
def send_and_capture(shell, command, timeout=5):
"""
Helper: Send a command via shell, capture full output.
"""
shell.send(command + '\n')
time.sleep(timeout) # Initial buffer
output = ''
max_wait = 30 # Safeguard loop
wait_count = 0
while wait_count < max_wait:
if shell.recv_ready():
output += shell.recv(4096).decode('utf-8')
wait_count = 0
else:
time.sleep(0.1)
wait_count += 1
return output
def backup_config(ip, username, password):
"""
SSH to Cisco C1300 switch, enable datadump, grab multiple show outputs (no enable needed), and save bundled to local file with IP+date.
Returns filename on success or None on failure.
"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
timestamp = datetime.now().strftime('%Y%m%d') # e.g., 20251016
filename = f"{ip.replace('.', '_')}_{timestamp}.txt" # e.g., 192_168_1_10_20251016.txt
filepath = os.path.join(backup_dir, filename)
try:
# Connect
client.connect(
hostname=ip,
username=username,
password=password,
timeout=10,
look_for_keys=False,
allow_agent=False
)
# Interactive shell
shell = client.invoke_shell()
time.sleep(2)
# Disable pagination with C1300-specific command
shell.send('terminal datadump\n')
time.sleep(1)
while not shell.recv_ready():
time.sleep(0.1)
shell.recv(4096).decode('utf-8') # Drain echo
# Capture outputs
run_config = send_and_capture(shell, 'show running-config', timeout=10) # Longer for config
int_status = send_and_capture(shell, 'show interfaces status')
version = send_and_capture(shell, 'show version')
clock = send_and_capture(shell, 'show clock')
# Exit
shell.send('exit\n')
time.sleep(1)
client.close()
# Bundle with separators
audit_text = f"""=== RUNNING CONFIG ===
{run_config}
=== INTERFACES STATUS ===
{int_status}
=== VERSION ===
{version}
=== CLOCK ===
{clock}
"""
# Trim to clean sections where possible
audit_text = audit_text.replace('\x1b[0m', '') # Strip ANSI codes if any
with open(filepath, 'w') as f:
f.write(audit_text)
line_count = len(audit_text.splitlines())
print(f"Audit saved: {filepath} ({line_count} lines)")
return filepath
except paramiko.AuthenticationException:
print(f"Auth failed on {ip}")
return None
except paramiko.SSHException as e:
print(f"SSH error on {ip}: {e}")
return None
except Exception as e:
print(f"Unexpected error on {ip}: {e}")
return None
finally:
try:
client.close()
except:
pass
if __name__ == "__main__":
# Validate file
if not os.path.exists(ips_file_path):
print(f"ERROR: IP file not found: {ips_file_path}")
sys.exit(1)
# Load IPs
with open(ips_file_path, 'r') as f:
switch_ips = [line.strip() for line in f if line.strip()]
if not switch_ips:
print("ERROR: No IPs in file.")
sys.exit(1)
# Cred check
if username == 'your_username' or password == 'your_password':
print("ERROR: Update credentials in script (lines 8-9).")
sys.exit(1)
print(f"Loaded {len(switch_ips)} switches from {ips_file_path}")
print(f"Audits will save to {backup_dir}")
print("\nStarting device audits...\n")
success_count = 0
for ip in switch_ips:
result = backup_config(ip, username, password)
if result:
success_count += 1
print(f"\nAudit complete: {success_count}/{len(switch_ips)} successful.")
print("Check D:\\python for bundled files.")
Code Deep Dive
- Setup Basics: Grabs essentials, preps D:\python\—Windows-friendly paths with raw strings.
- Capture Helper:
send_and_capture
is your workhorse—sends, times out smartly, loops to nab every byte. Extra buffer for verboseshow run
. - Main Action (
backup_config
):
- SSH handshake, shell spin-up.
terminal datadump
: The 1300 magic—bypasses pagination wherelength 0
flops.- Command Barrage:
show running-config
(tuned timeout),show interfaces status
(port vibes),show version
(firmware facts),show clock
(time truth). - Bundle & Polish: Sections with === tags, ANSI scrub for clean reads.
- File Drop: IP+date naming, line count for quick QA.
- Launcher: IP load, cred nag, loop with success tracking.
Execution Guide
- Swap in creds, point
ips_file_path
to your list. - Sample
access_switch.txt
:
192.168.1.10
192.168.1.11
10.0.0.5
- Run:
python cisco_1300_audit_datadump.py
. - Console Tease:
Loaded 3 switches from C:\path\to\your\access_switch.txt
Audits will save to D:\python
Starting device audits...
Audit saved: D:\python\192_168_1_10_20251016.txt (823 lines)
Audit saved: D:\python\192_168_1_11_20251016.txt (756 lines)
Auth failed on 10.0.0.5
Audit complete: 2/3 successful.
Check D:\python for bundled files.
Inside a File (C1300-Style Output):
=== RUNNING CONFIG ===
config-file-header
KTI-sw01
v4.1.6.54 / RLSB4.1.6_951_410_024
... [full config, no truncation] ...
end
=== INTERFACES STATUS ===
Port Name Status Vlan Duplex Speed Type
Gi1/0/1 connected 1 a-full a-1000 10/100/1000BaseTX
... [complete port roster] ...
=== VERSION ===
Cisco IOS XE Software, C1300-8T2E (Industrial Ethernet)
... [hardware/software deets] ...
=== CLOCK ===
*13:45:22.123 UTC Wed Oct 16 2025
Field-Tested Tweaks
- Syntax Sensitivities: If your 1300 firmware varies (e.g., pre-4.1), test
terminal datadump
manually—fallback to space-sending loops if needed. - Expand the Arsenal: Add
show vlan brief
orshow env temp
? Justsend_and_capture
it in. - Bulk Mode: 100+ devices? Thread with
concurrent.futures
(cap at 10 concurrent to spare your TACACS). - Post-Process:
awk '/down/{print $1}'
for err-disable hunts, orpandas
for CSV exports. - 1300 Prods: These run hot in industrial spots—pair audits with SNMP for env monitoring.
- Debug Drill: Log
len(output)
per command to confirm fullness.