1

tl/dr: Is there a simple way to get a command's output during a telnet session with Python?


I am writing a Python script (using 3.4) to automate actions during a telnet session. I want to be able to telnet in, write to the command line to perform an action, and then return the output from that command. I have a method, but it seems like it could be improved upon, and it is not very dynamic.

My current method:

def telnet_in(ip):
   """Telnets into the device"""
   tn = telnetlib.Telnet(ip)
   tn.read_until(b"login: ")
   tn.write(TEL_PASS)
   tn.read_until(PROMPT) # Clear buffer of output
   return tn

This will telnet into my device just fine for my setup. The next part I try to cat some information from the device:

def get_model(ip):
   """Returns the device's model"""
   session = telnet_in(ip)
   session.write(b"cat " + MODEL_DIR + b"model\r\n")
   time.sleep(1) # Give it time to enter buffer
   model = session.read_very_eager()
   model = model[26:-4] # Clean up output to only return model
   model = decode_byte_str(model) # Decode to str
   telnet_exit(session)
   return model

A few things I have noticed/tried:

  1. I have to use the byte str 'b' for when I use tn.write()
  2. I have to use \r as well.

Without those, I do not get a return or I get an error.

Additionally:

  1. The output I get from model = session.read_very_eager() will return the string that I used for my command as well as the prompt after the command's returned output. I have to trim the string down to size to just get the model str.
  2. Given that I have to use 'b' for my strings, the string returned is also a byte string and needs to be decoded. I handle that with my decode_byte_str() just fine:
def decode_byte_str(byte_str):
   """Decodes a byte string using utf-8"""
   return byte_str.decode("utf-8")

I am able to get the string in the end that I am looking for, but it seems to be such a convoluted way to just get a returned string. Also, this method is not dynamic, and I have to write individual functions for each info that I want to obtain, given that I have to trim the strings to a certain size. Certainly, I could just "pass" the size that needs to be trimmed, but that is additional work that really shouldn't be needed. Further, if I want to write a function that takes a variable that the user inputs, then I wouldn't know the exact amount to trim before the output. I suppose I could get the length of the str, and then pass that length in, but again that further complicates what should be a simple task.

So, my question is: Is there a simple way to get the command's output during a telnet session with Python? Also, I am not married to using telnetlib. If there is a better lib or method then I am open to those as well.

Thanks in advance!

EDIT: Here is my updated version, if anyone wants to use it until we can find an easier/better way:

def telnet_in(ip):
   """Telnets into a device"""
   tn = telnetlib.Telnet(ip)
   tn.read_until(b"login: ")
   tn.write(TEL_PASS)
   tn.read_until(PROMPT) # Clear buffer of output
   return tn

def telnet_exit(session):
   """Exits a telnet session"""
   session.write(b"exit\r\n")

def _encode_str(in_str):
   """Encodes a string to a byte string"""
   return bytes(in_str, encoding="utf-8")

def _decode_byte_str(byte_str):
   """Decodes a byte string using utf-8"""
   return byte_str.decode("utf-8")

def _get_cmd_output(session, cmd_str):
   """Returns output from a command"""
   cmd_str_len = len(cmd_str)
   bcmd_str = _encode_str(cmd_str) # Encode str to byte str
   session.write(bcmd_str)
   time.sleep(0.1) # Give it time to enter buffer
   cmd_out = session.read_very_eager()
   cmd_out = cmd_out[cmd_str_len:PROMPT_LEN] # Trim output to only return command's returned output
   cmd_out = _decode_byte_str(cmd_out) # Decode to a str
   return cmd_out

def get_model(ip):
   """Returns the device's model"""
   session = telnet_in(ip)
   cat_model = "cat " + INFO_DIR + "model\r\n"
   model = _get_cmd_output(session, cat_model)
   telnet_exit(session)
   return model

def get_device_id(ip):
   """Returns the device id"""
   session = telnet_in(ip)
   cat_device_id = "cat " + INFO_DIR + "device_id\r\n"
   device_id = _get_cmd_output(session, cat_device_id)
   telnet_exit(session)
   return device_id

Works for my purposes. I still wonder if there is already some built-in lib that can already handle this stuff.

Ebad
  • 131
  • 11

0 Answers0