Appending output of unsucessful connect attempts output to a .txt file - networking

I'm having problems saving the output of a script that applies configs to multiple devices and lets me know if a connection to a device has timed out. The script successful logs into the devices, runs the commands, and displays the output. It saves the timed out devices to .txt file, however if multiple devices experience timeouts, it deletes the line with the timed out device and only displays the name of the last device that timed out. Could someone please show me what I should add to my code, so that the names of the all the devices that the script can't connect to?
Timeouts=open("Connection time out.txt", "a")
try:
net_connect = ConnectHandler(**ios_device)
except (AuthenticationException):
print ('Authentication Failure: ' + ip_address_of_device)
continue
except (NetMikoTimeoutException):
print ('Timeout to device: ' + ip_address_of_device)
Timeouts.write(ip_address_of_device)
continue
except (EOFError):
print ('End of file whilte attempting device: ' + ip_address_of_device)
continue
except (SSHException):
print ('SSH might not be enabled: ' + ip_address_of_device)
continue
except Exception as unknown_error:
print (str(unknown_error))
continue
#with open ("Connection time out.txt") as f:
#for line in f:
#print (line),
output=net_connect.send_config_set(commands_list)
print(output)

f = open("demofile2.txt", "a")
f.write("Now the file has more content!")
f.close()
#open and read the file after the appending:
f = open("demofile2.txt", "r")
print(f.read())

Related

Telnetlib doesn't seem to be passing .write commands

I'm a python noob here just trying to learn a new skill so please be gentle :)
After executing the following script it appears that my script creates a telnet session and I can see the cisco devices banner but is not passing the username/password when prompted.
I've tried changing tn.read_until() and tn.read_very_eager() neither of which is triggering the script to move on to write the desired input. I've also tried forcing the username and password to be input as a byte as well as adding + '\n' to my write functions. I've also used sleep to pass a little extra time to wait for the banner to finish printing out.
tldr: when executing the script I see the username prompt, but can't get further than that.
any assistance here is welcomed.
'''
from time import sleep
import telnetlib
from telnetlib import Telnet
from getpass import getpass
Username = input('please provide your username ')
password = getpass()
# f is the .txt document that lists the IP's we'll be using.
f = open('devicess.txt')
for line in f:
print ('Configuring Device ' + (line))
device = (line)
#open connection to variable
tn = telnetlib.Telnet(device)
#For those devices in the above list, connect and run the below commands
for device in f:
tn.expect('Username: ')
tn.write(Username)
tn.expect('Password: ')
tn.write(password)
tn.write('show ver')
print('connection established to ' + device)
tn.write('logout')
output = tn.read_all()
print(output)
print('script complete')
'''

read() does not read data from pty despite they are

My program is supposed to emulate external device that is usually connected via COM port (/dev/ttyUSB0). The program opens a pty and waits for commands. Here is the code:
HostPty::HostPty(const string & HostPty_name)
{
char name[100] = {0};
int res = openpty(&_master, &_slave, name, NULL, NULL);
printf("Name: %s\n", name);
}
string HostPty::nextString()
{
static const int BUF_SIZE = 4096;
char buf[BUF_SIZE];
size_t idx = 0;
while(true)
{
// Read symbols one by one until new line is found
size_t received_size = read(_master, buf + idx, 1);
printf("Received a symbol: %02x\n", buf[idx]);
// Stopping at new line
if(buf[idx] == '\n')
break;
idx++;
}
return string(buf, idx);
}
To test this code I am using miniterm.py terminal emulator connecting to /dev/pty/6 (or whatever is created with openpty) and send text commands over there.
When I type commands manually everything works fine - I receive chars one by one as expected. But when I paste a piece of multiline text this code receives only first byte until I put a new line symbol (even though there are multiple newline symbols in the text I paste).
Any ideas how to fix that?
Any ideas how to fix that?
I don't know which kind of Unix you have. I just tried to reproduce your problem under Linux; but pasting lines work fine on my computer so I cannot reproduce the problem.
If your Unix variant has a system call tracer (Linux: strace, SunOS/Solars: truss, FreeBSD: strace, MacOS: dtruss (?)), I'd trace the system calls:
strace -f -o file_myprog.out ./my_program
miniterm /dev/pty/6
(Note the -f which means that the system calls of sub-processes created by fork() are also debugged. This is necessary because Python will create such sub-processes.)
Now reproduce the situation when the program does not behave correctly and kill my_program using pkill -KILL my_program. (Send the -KILL signal to ensure that my_program is killed immediately.)
Do that again - this time debugging miniterm and killing miniterm in the "wrong situation":
./my_program
strace -f -o file_miniterm.out miniterm /dev/pty/6
At the end of the two output files (file_myprog.out and file_miniterm.out) you can see the last "actions" the two programs were doing before you killed them. There are various scenarios possible:
miniterm was sending the data to /dev/pty/6 but your program did not receive any data. In this case there is a problem with the virtual console itself.
miniterm did not send the data to /dev/pty/6 for some reason. In this case you have a problem with miniterm.
miniterm did not even receive the data pasted using read()...

KeyboardInterrupt handling is extremely slow. Where is the problem?

I'm currently trying to write a script to read a shell via paramiko and, by far, if I prompt a single command it works great.
the problem is that my actual goal is to handle a debug flow and of course I cannot use a timeout because the script should listen without time limitations.
So the other option is to let the user stop the flow with ctrl-c. I added a "try, except" handler like
except (IOError, SystemExit):
raise
except KeyboardInterrupt:
print ("Crtl+C Pressed. Shutting down.")
and it seemed like it wasn't working: nothing happened when pressing ctrl-c. But then I realized that it was just taking forever: after a few minutes the script actually stops and the message appears.
Does anyone know how to handle this problem?
just for the reference here's my code
import paramiko
import time
import re
import socket
import os
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
address = '192.168.1.1'
username = 'admin'
password = ''
ssh.connect(address, port=22, username = username, password = password)
shell = ssh.invoke_shell(height=400)
shell.settimeout(2)
def prompt_console(command = '', channel = shell, timeout = False):
print(channel.recv(9999).decode('utf-8')) #<-- this is for removing the initial prompt from buffer
if timeout == False:
shell.settimeout(3600) #<--increasing the timeout
channel.send(command+'\n')
log = ''
while True:
try:
log += channel.recv(1).decode('utf-8') #<--every loop it loads a char into the "log" variable
if log[-9:] == '--More-- ':
shell.send(" ")
log.replace('--More-- \r \r\t\t','\r\t\t')
if len(re.findall('.*\n',log))>0: #<--it yields every line to python console
yield log
log = ''
except (IOError, SystemExit):
raise
except KeyboardInterrupt:
print ("Crtl+C Pressed. Shutting down.")
I also tried to put the try-except outside the while loop but it didn't work. I also tried many suggestions that I've found on google but they didn't work either: they all stop the script eventually but for all of them it takes 5-10 minutes.

Write and read from a serial port

I am using the following python script to write AT+CSQ on serial port ttyUSB1.
But I cannot read anything.
However, when I fire AT+CSQ on minicom, I get the required results.
What may be the issue with this script?
Logs:
Manual Script
root#imx6slzbha:~# python se.py
Serial is open
Serial is open in try block also
write data: AT+CSQ
read data:
read data:
read data:
read data:
Logs:
Minicom console
1. ate
OK
2. at+csq
+CSQ: 20,99
3. at+csq=?
OKSQ: (0-31,99),(99)
How can I receive these results in the following python script?
import serial, time
#initialization and open the port
#possible timeout values:
# 1. None: wait forever, block call
# 2. 0: non-blocking mode, return immediately
# 3. x, x is bigger than 0, float allowed, timeout block call
ser = serial.Serial()
ser.port = "/dev/ttyUSB1"
ser.baudrate = 115200
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
ser.timeout = None #block read
#ser.timeout = 0 #non-block read
ser.timeout = 3 #timeout block read
ser.xonxoff = False #disable software flow control
ser.rtscts = False #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 2 #timeout for write
try:
ser.open()
print("Serial is open")
except Exception, e:
print "error open serial port: " + str(e)
exit()
if ser.isOpen():
try:
print("Serial is open in try block also")
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput()#flush output buffer, aborting current output
#and discard all that is in buffer
#write data
ser.write("AT+CSQ")
time.sleep(1)
# ser.write("AT+CSQ=?x0D")
print("write data: AT+CSQ")
# print("write data: AT+CSQ=?x0D")
time.sleep(2) #give the serial port sometime to receive the data
numOfLines = 1
while True:
response = ser.readline()
print("read data: " + response)
numOfLines = numOfLines + 1
if (numOfLines >= 5):
break
ser.close()
except Exception, e1:
print "error communicating...: " + str(e1)
else:
print "cannot open serial port "
You have two very fundamental flaws in your AT command handling:
time.sleep(1)
and
if (numOfLines >= 5):
How bad are they? Nothing will ever work until you fix those, and by that I mean completely change the way you send and receive command and responses.
Sending AT commands to a modem is a communication protocol like any other protocols, where certain parts and behaviours are required and not optional. Just like you would not write a HTTP client that completely ignores the responses it gets back from the HTTP server, you must never write a program that sends AT commands to a modem and completely ignores the responses the modem sends back.
AT commands are a link layer protocol, with with a window size of 1 - one. Therefore after sending a command line, the sender MUST wait until has received a response from the modem that it is finished with processing the command line, and that kind of response is called Final result code.
If the modem uses 70ms before it responds with a final result code you have to wait at least 70ms before continuing, if it uses 4 seconds you have to wait at least 4 seconds before continuing, if it uses several minutes (and yes, there exists AT commands that can take minutes to complete) you have to wait for several minutes. If the modem has not responded in an hour, your only options are 1) continue waiting, 2) just give up or 3) disconnect, reconnect and start all over again.
This is why sleep is such a horrible approach that in the very best case is a time wasting ticking bomb. It is as useful as kicking dogs that stand in your way in order to get them to move. Yes it might actually work some times, but at some point you will be sorry for taking that approach...
And regarding numOfLines there is no way anyone in advance can know exactly how many lines a modem will respond with. What if your modem just responds with a single line with the ERROR final result code? The code will deadlock.
So this line number counting has to go completely away, and instead your code should be sending a command line and then wait for the final result code by reading and parsing the response lines from the modem.
But before diving too deep into that answer, start by reading the V.250 specification, at least all of chapter 5. This is the standard that defines the basics of AT command, and will for instance teach you the difference between a command and a command line. And how to correctly terminate a command line which you are not doing, so the modem will never start processing the commands you send.

Python socket sendall randomly fails

I have a simple script which transfers an image file from one machine to another,
does image processing and returns a result as "dice count".
The problem is that randomly the image received is partially grey. There seems no
reason as to when the transfer is incomplete and I see no other issues in the code.
The client gives no error or any indication that sendall failed or was incomplete.
Thanks guys.
server code:
def reciveImage():
#create local buffer file
fo = open("C:/foo.jpg", "wb")
print "inside reciveImage"
while True:
print "inside loop"
data = client.recv(4096)
print "data length: ", len(data)
fo.write(data)
print "data written"
if (len(data) < 4096):
break
print "break"
fo.close()
print "Image received"
And the (simplifyed) client code:
data = open("/home/nao/recordings/cameras/image1.jpg", "rb")
# prepare to send data
binary_data = data.read()
data.close()
sock.sendall(binary_data)
Normal server output:
Client Command: findBlob. Requesting image...
inside reciveImage
inside loop
data length: 4096
data written
#... This happens a bunch of times....
inside loop
data length: 4096
data written
inside loop
data length: 1861
data written
Image received
dice count: 0
Waiting for a connection
But randomly it will only loop a few times or less, like:
Client Command: findBlob. Requesting image...
inside reciveImage
inside loop
data length: 1448
data written
Image received
dice count: 0
Waiting for a connection
recv does not block until all data are received, it only blocks until some data are received and returns them. E.g. if the client send first 512 bytes and then a second later another 512 byte your recv will return the first 512 bytes, even if you asked for 4096. So you should only break if recv returns, that no more data are available (connection closed).

Resources