I am trying to send command to a serial com to a gps hardware from the windows with below python script using pyserial.
The script runs fine and do what is expected from the command.Except I have to press "Enter" , only then the command performs the expected result.
I have tried many ways to send enter but not able to perform the command. How can I prevent pressing enter with the command below to achieve the task. Please assit. This seems very easy but I am not able to get past through it from past 1 week.
import serial
port = "COM103"
baud = 115200
ser = serial.Serial(port, baud, timeout=1)
if ser.isOpen():
print(ser.name + ' is open...')
while True:
if cmd == 'exit':
ser.close()
exit()
else:
print('Sending..')
ser.write("run MODE-55")
ser.write("\r")
You need to check which command does your device support, it can be \r, \n, \r\n. Since you are using Windows, it seems that the last one is used, because \r\n is a sequence for Enter in Windows. Or this could be \n because \r was sent already.
Also, you don't need to use two commands where it can be done by one:
ser.write("run MODE-55\r\n")
Related
I am working on a script to pull configs from Cisco devices in GNS3. Currently it is using a hard coded IP & port due to another separate issue but this is the code I am currently using.
import getpass
import telnetlib
print "Getting running-config 127.0.0.1:5002"
tn = telnetlib.Telnet("127.0.0.1","5002")
tn.write("terminal length 0\n")
tn.write("show run\n")
tn.write("exit\n")
readoutput = tn.read_until("exit")
saveoutput = open("C:\Programdata\switch.txt","w")
saveoutput.write(readoutput)
saveoutput.write("\n")
saveoutput.close
print tn.read_all()
If I comment out the readouput and saveoutput blocks of code the script runs through as fast as I would expect it to. However once I leave that code in there it just sits and hangs. I have put print() commands in to verify and it hangs on the readoutput line. I have tried both tn.read_all & tn.read_until (without and without a string parameter) and neither works.
Even though the readoutput is not working I know something is occurring because if I telnet into the switch with telnet 127.0.0.1 5002 in a command prompt it comes up without issue as well as being able to progress through my terminal commands.
Edit:
I did more testing with this today and found out through the use of a lot of sleep timers and printing to the terminal what was going on. As it turns out for some reason the telnet session is not actually pressing enter when it should. I tried changing the tn.write("text\n") to tn.write("text" + "\n")and even splitting that into two write commands, but none of it works. Below is a telnet session I opened after some failed attempts at making the script work. Note all the commands are just sitting there in line? If I change the readoutput to look for "xit" which is the text on the first line of the ios console, then it will find it in telnet and print everything in the telnet session to that point.
If anyone knows why "\n" is not actually hitting enter I would greatly appreciate the help as this should be my last major hurdle to making the program this script is a part of work.
The reason for this behaviour is because \n isn't actually carriage return (CR) - it's line feed (LF) in string, and different systems may have different EOL implementation (the most obvious example being Linux's \n versus Windows's \r\n). In case of Cisco IOS, it seems that \r is enough, although I can't currently verify it.
Try adding \r\n as this is default Telnet behaviour according to the spec, that should work.
All of your code is True and also both of :
tn.write("text\n")
tn.write("text" + "\n")
Is true. Just one missing is b :
Your code should be like this :
tn.write(b"en" + b"\n")
tn.write(b"terminal length 0\n")
tn.write(b"show run\n")
tn.write(b"exit\n")
I have an issue that has been giving me a headache for a few days. I am using the Paramiko module with Python 2.7.10 and I'd like to issue multiple commands to a Brocade router, but only return output from one of the given commands like so:
#!/usr/bin/env python
import paramiko, time
router = 'r1.test.example.com'
password = 'password'
username = 'testuser'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(router, username=username, password=password)
print('Successfully connected to %s' % router)
remote_conn = ssh.invoke_shell()
output = remote_conn.recv(1000)
# Disable paging on Brocade.
remote_conn.send('terminal length 0\n')
# Check interface status.
remote_conn.send('show interfaces ethernet 0/1\n') # I only want output from this command.
time.sleep(2)
output = remote_conn.recv(5000)
print(output)
If I were to print the full output it would contain everything issued to the router, but I only want to see output from the show interfaces ethernet 0/1\n command.
Can anyone help with this issue?
One final thing I would like to ask. I want to filter through the output variable and check for occurrences of strings like "up" or "down", but I can't seem to get it to work because everything in the output appears to be on new lines?
For example:
If I iterate over the output variable in a for loop I get all of the characters in the variable like so:
for line in output:
print(line)
I get an output like this:
t
e
r
m
i
n
a
l
l
e
n
g
t
h
0
Any way around this?
Again,
Thanks in advance for any help.
Best regards,
Aaron C.
After reading all of the comment I have made the following changes:
#!/usr/bin/env python
import paramiko, time
router = 'r2.test.example.com'
password = 'password'
username = 'testuser'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(router, username=username, password=password)
print('Successfully connected to %s' % router)
remote_conn = ssh.invoke_shell()
output = remote_conn.recv(1000)
# Disable paging on Brocade.
remote_conn.send('terminal length 0\n')
time.sleep(2)
# Clearing output.
if remote_conn.recv_ready():
output = remote_conn.recv(1000)
# Check interface status.
remote_conn.send('show interfaces ethernet 4/1\n') # I only want output from this command.
time.sleep(2)
# Getting output I want.
if remote_conn.recv_ready():
output = remote_conn.recv(5000)
print(output)
# Test: Check if interface is up.
for line in output.split('\n'):
if 'line protocol is up' in line:
print(line)
Everything works great now.
Thank you for all the help.
Best regards,
Aaron C.
For your second question: Though I am not specialist of paramiko, I see that function recv, according to the doc, returns a string. If you apply a for loop on a string, you will get characters (and not lines as one might perhaps expect). The newline is caused by your use of the print function as explained on this page, at paragraph 6.3.
I haven't studied what paramiko suggests to do. But why don't you treat the full string as a single entity? For example, you could check the presence of "up" as:
if "up" in output:
Or, if that suits your needs better, you could split the string into lines and then do whatever test you want to do:
for line in output.split('\n'):
If you can, the exec_command() call provides a simpler mechanism to invoke a command. I have seen Cisco switches abruptly drop connections that try exec_command(), so that may not be usable with Brocade devices.
If you must go the invoke_shell() route, be sure to clear all pending output after connecting and after send('terminal length 0\n'), checking recv_ready() before calling recv() to avoid blocking on reading data that might not ever arrive. Since you are controlling an interactive shell, sleep() calls might be needed to allow the server adequate time to process and send data, or it might be necessary to poll the output string to confirm that your last command completed by recognizing the shell prompt string.
I'm playing around with this serial module in python. I have a little problem with it. I want my script to get a char from the console send it to an AVR board, and read back the response.
Everytime I read from the USB port, and print it out, I see the previous result. Why's that?
For example:
I write 5
I read nothing
I write 6
I read 5
import serial
import sys, time
port=serial.Serial(
port='/dev/ttyUSB0',\
baudrate=9600,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=0)
i=0
tmp = 0
while True:
tmp=raw_input('send: ')
port.write(tmp)
port.flushOutput()
print port.read(1)
port.flushInput()
From the documentation: "Writes are blocking by default, unless writeTimeout is set. For possible values refer to the list for timeout above." Try setting writeTimeout=0 as well in your constructor.
You are probably receiving a single unexpected byte on startup - either the microcontroller is sending it, or it might be noise from connecting a plug. As you are only reading a single byte for each string transmitted, you will always be off by one.
Instead of port.read(1), try:
while True:
tmp=raw_input('send: ')
port.write(tmp)
port.flushOutput()
print port.read(port.inWaiting())
port.flushInput()
This would also have happened if your typed in more than one character at the input prompt.
I use teraterm as my client-console and save the console log somewhere.
When I open the teraterm and do something on my COM1 serial port (attached with a device),
it will print messages on the screen and write to the log file simultaneously,
if I want to watch the log , to detect if any special word occurs .
I thought if I use the "open" method , I can only get the whole content at the opened time , but can not get the latest content the teraterm write after the opened time?
How could I achieve this?
Thank you all in advance~
Periodically check file size:
import os
import time
log_path = '/tmp/com1.log'
special_word = 'magic'
lastsize = 0
while 1:
if os.path.exists(log_path) and os.path.getsize(log_path) > lastsize:
with open(log_path) as f:
f.seek(lastsize)
for line in f:
if special_word in line:
print('Special word found')
lastsize = f.tell()
time.sleep(1)
You could use teraterm's macro langauge, it allows the developers to extend the behaviour of teraterm.
For your specific case, teraterm's macro language provides wait family of functions to wait for a particular sequence of word (or) pattern. Mind that teraterm macro language is not python, but it has its own syntax.
; wait for special world 'hello'
wait 'hello'
if result == 0 goto your_own_logic
There are other ways if you want to have a python only solution. Instead of using teraterm to connect with serial port, you could use pyserial python library to connect with serial port.
read_all()" to read data from a cisco device.
some time it reads the data and sometime it won't read and gives empty string.
I tried below 2 commands but still it's not consitently reading data.
data=tn.read_until("exit")
data= tn.read_all()
please give some inputs i am new to python.
code i am using:
_command2='show chassis'
print 'Commands issued............'
#ISSUE COMMANDS VIA TELNET
tn.write("term len 0\r")
#tn.read_until(" ")
#tn.write(_command1+"\r")
tn.write(_command2+"\r")
tn.write("exit\r" )
print 'Read telnet data............'
#READ TELNET DATA
#data=tn.read_eager()
data=tn.read_until("exit")
#data= tn.read_all()
#print data
print 'Telnet data read successfully............'
I too faced the same problem..This would help:
tn = telnetlib.Telnet('64.0.0.1')
tn.write('ls \r\n')
data = ''
while data.find('#') == -1:
data = tn.read_very_eager()
print data
This snippet reads the info after a command being executed.
And reads till '#' prompt is shown.
Short answer:
Use time.sleep(1) in between write commands
Long answer:
When you enter a command on a Cisco IOS console, it blocks until the command completes. Any input you enter into the console while the command was running is piped into the running command, much like STDIN works on a bash shell. However in bash, if a commands doesn't explicitly read the input, upon the exit of the program bash takes the unconsumed input and interprets it as a shell command. So if you want to run two commands one after another, where the first command does not read from STDIN, you can enter the second command while first command is running, i.e. you don't have to wait for the first command to finish before you enter another command. This sort of a buffering mechanism makes telnet scripting easy and we have grown to expect this from mature shells. Apparently Cisco IOS lacks this feature, and so you have to make sure you don't enter your commands too soon. There are two ways I can think of, to go about it:
Wait for a fixed amount of time between commands. Usually 1 second is a safe bet for most commands.
Parse the output after each command until you find the prompt, then enter the next command, then parse again, and so on.
Use:
tn.read_very_eager()
instead of tn.read_all() - read_all waits until the connection is closed
#yogi 's answer is almost right.
but some details to be explained
data = ''
finish = '' #m1
while data.find(finish) == -1:
data += tn.read_very_eager() # m2
print data
m1: there is what your telnet server returns when command finished
m2: there should be +=, because some command results has several lines