How to parse a Linux terminal error message in Python? - python

I have written a small Python code to test it for a bigger project. The subprocess works great if everything's fine. But I want to parse the output error message for particular errors so I can figure out what the error is such as- IP not in network, or wrong username, wrong password.
Even the print at the end doesnt work. My interest in however not to print those. I was merely checking if the parsing works!
import sys
import subprocess
import os
ip = "192.168.1.20"
password = "password"
username = "sam"
ans = subprocess.check_output(['sudo','xfreerdp','-p',password, ip])
for line in ans.split('\n'):
if "protocol security negotiation" in line:
print "Not Windows!"
print "JUST TO test if this print works and it doesnt!!"

Try using try..except
import sys
import subprocess
import os
ip = "192.168.1.20"
password = "password"
username = "sam"
try:
ans = subprocess.check_output(['sudo','xfreerdp','-p',password, ip])
except subprocess.CalledProcessError as e:
ans = e.output
for line in ans.split('\n'):
if "protocol security negotiation" in line:
print "Not Windows!"
print "JUST TO test if this print works and it doesnt!!"

You need to redirect STDERR in order to check messages printed to it. Add:
subprocess.check_output(['sudo','xfreerdp','-p',password, ip], stderr=subprocess.STDOUT)

Related

Python script to catch failed commands or warnings messages

I have a little script that telnets into a network switch and executes commands. It works fine but I need it stop and show an error message if any of the commands fail or network give a waning or something.
Here is the code:
import sys
import telnetlib
HOST = "10.10.10.1"
user = "Test"
password = "TestPW"
tn = telnetlib.Telnet(HOST)
tn.read_until("username: ")
tn.write(user + "\n")
tn.read_until("password: ")
tn.write(password + "\n")
n, match, previous_text = tn.expect([r'Login incorrect', r'\$'], 1)
if n == 0:
print "Invalid Credentials"
tn.close()
else:
tn.write("Term len 0\n")
#Reads data from commands.txt file and executes it line by line
with open("commands.txt") as commands:
singlecommand = commands.read()
tn.write(singlecommand)
print singlecommand
#Need exception/error checking to catch fail commands or warnings.
tn.write("exit\n")
tn.write("y\n")
print tn.read_all()
tn.close()
I want the script to stop executing more commands after a fail command or a warning from CLI that something maybe wrong. It already has the print function so it should display the error message and command that failed.
Here is a example of a failed command:
% Invalid input detected at '^' marker.
Here is an example warning message:
%Warning:
You can use Try/Except statements.
They're related to the Errors and Exceptions part of the Python docs.
Example:
try:
wrong_sum = "a" + 2
except ValueError:
print "You got a Value Error"
else:
break
you can extract the message based on key word appeared in failed command, then raise the exception.
for example:
try:
if '%Warning' == message[:8]:
raise Exception('Test')
except Exception:
print message

How do I open a file in python and insert one or more inputs to it?

I've been trying to code a bit of a "game" to help others learn python, but I've run into a wall right after I jumped out of the brainstorming phase.
See, it involves making a script open another script, and then insert input to it. For example:
username = raw_input('Insert username:')
password = raw_input('Insert password:')
if username == user:
if password == 1234:
print('Congratulations, you cracked it!')
This would be my source code. Then I'd have another code, in which I'd write something to open the former script, insert "user" as if I'd typed it myself in the command prompt, and then tried to insert every number between 0 and, say, 10000. So something like:
for n in range(0, 10000)
[Insert script to open file]
[input 'user']
[input n]
How would I go on about to code the last part?
The subprocess module lets you run another program—including a script—and control its input and output. For example:
import subprocess, sys
p = subprocess.Popen([sys.executable, 'thescript.py'], stdin=subprocess.PIPE)
p.stdin.write('user\n')
p.stdin.write('{}\n'.format(n))
p.wait()
If you can build all the input at once and pass it as a single string, you can use communicate.
If you also want to capture its output, add another PIPE for stdout.
import subprocess
p = subprocess.Popen(['python', 'thescript.py'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = p.communicate('user\n{}\n'.format(n))
For details on how this works, read the documentation; it's all explained pretty well. (However, it's not organized perfectly; you might want to read the opening section, then skip down to "Replacing Older Functions", then read the "Frequently Used Arguments", then come back to the top and go through in order.)
If you need to interact with it in any way more complicated than "send all my input, then get all the output", that gets very hard to do correctly, so you should take a look at the third-party pexpect module.
Would this be what you wanted?
import subprocess
for n in range(0, 10000):
p = subprocess.Popen("python another_script.py", shell=True,
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write("user\n" + str(n) + "\n")
out = p.stdout.read()
if "cracked" in out:
print "cracked: " + str(n)
break
Okay, I did it. Thanks for the help guys, but I settled with using modules.
I made my own small module like this:
Filename: pass1
def insertpassword(username, password):
if username == 'user':
if password == '12345':
print('You did it!')
Then what I do is:
import pass1
pass1.insertpassword(raw_input('Insert username:'),raw_input('Insert password:'))
As for the cracking:
import pass1
for n in range(0, 100000):
pass1.insertpassword('user', str(n))
Thanks anyway, everyone.

os.setuid doesn't change current user

I wanted to change current user for script execution. I did this
import os
newuid = pwd.getpwnam('newuser').pw_uid
os.setuid(newuid)
print('User :' + getpass.getuser());
I am still getting root. Is there better way than this? I want switch user once and then continue rest of the commands execution in the script with that new user.
getpass.getuser() doesn't use getuid() or geteuid() to get the current user.
http://docs.python.org/3/library/getpass.html#getpass.getuser
This function checks the environment variables LOGNAME, USER, LNAME and USERNAME, in order, and returns the value of the first one which is set to a non-empty string. If none are set, the login name from the password database is returned on systems which support the pwd module, otherwise, an exception is raised.
After trying modules os, subprocess, getpass, I realised that the problem is not whether the user is set. The user gets set or gets changed using os.setuid, however, the methods from modules to get username like os.getlogin(), getpass.getuser(), actually does not get username properly. If you run a shell command whoami or idusing subprocess.Popen() or os.system(), you will get the changed user. These are little puzzled outputs for me. Below is script which shows all these weird behaviours.
import os
import subprocess
import pwd
import getpass
#os.chdir("/tmp")
#uid = pwd.getpwnam('newuser').pw_uid
os.setuid(500) # newuser's id found from shell cmd line
print os.getuid()
p = subprocess.Popen(['id'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
# print os.system('useradd newuser1') # Try this commenting, it will not create, and then try commenting above line of setuid. i.e. it will become root, and then see the change.
# print os.getcwd()
print out,err
p = subprocess.Popen(['whoami'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
print out,err
print getpass.getuser()
print os.getlogin()
print os.system('whoami')

Telnet to router in Python Script

import getpass
import sys
import telnetlib
tn = telnetlib.Telnet("xxxxxxxx")
tn.write("xxxxxx" + "\n")
tn.write("xxxxxx" + "\n")
tn.write("show version\n")
tn.write("exit\n")
print tn.read_all()
Trying to telnet to a router and the script is hanging.... Not sure whats up. Have tried a debug but cant make head or toe of the output.
telnetlib.py(511): if self.irawq >= len(self.rawq):
telnetlib.py(512): self.rawq = ''
telnetlib.py(513): self.irawq = 0
telnetlib.py(516): buf = self.sock.recv(50)
This is where it hangs in the debug.
Thanks
William
I can answer this one. Managed to get it fixed.
The python script was going off the rails when the router asked for user input to see more information on the command.
So when i asked for a "show version" it would give out a lot of information onto the command line and then ask you hit space to see more.
To solve this the first command i execute is "term len 0". Stops it asking for any user input and just fires it all out at once.
below is the final script. Changed quite a bit but its works.
import sys
import telnetlib
tn = telnetlib.Telnet("xxxxxxxx")
TELNET_PROMPT="xxxxxxxxxx"
TIMEOUT=1
tn.write("xxxxxxx"+"\n")
tn.write("xxxxxxx"+"\n")
print tn.read_until(TELNET_PROMPT, TIMEOUT)
tn.write("term len 0" + "\n")
print tn.read_until(TELNET_PROMPT, TIMEOUT)
tn.write("show version" + "\n")
print tn.read_until(TELNET_PROMPT, TIMEOUT)
tn.write("exit"+"\n")
tn.close()

Need little assistance with pexpect module

Need assistance with the pexpect module
I have written a simple code which would clone a git repository from a server using ssh.
I'm facing couple of problems.
The password is shown in plain text.
I dont know a proper way to exit the program after the download. it throws out the following error...
Traceback (most recent call last):
File "ToDelete3.py", line 65, in <module>
# # if i == 1:
File "ToDelete3.py", line 36, in getRepository
i = p.expect([ssh_key,'password:',pexpect.EOF])
File "/usr/lib/python2.7/dist-packages/pexpect.py", line 1492, in interact
self.__interact_copy(escape_character, input_filter, output_filter)
File "/usr/lib/python2.7/dist-packages/pexpect.py", line 1520, in __interact_copy
data = self.__interact_read(self.child_fd)
File "/usr/lib/python2.7/dist-packages/pexpect.py", line 1510, in __interact_read
return os.read(fd, 1000)
OSError: [Errno 5] Input/output error
the code that I have written so far is :
command = 'git clone ssh://username#someserver/something.git'
ssh_key = 'Are you sure you want to continue connecting'
def gracefulExit():
print 'Password Incorrect !!!'
os._exit(1)
def getRepository():
p = pexpect.spawn(command,maxread=10000,timeout = 100)
p.logfile = sys.stdout # logs out the command
i = p.expect([ssh_key,'password:',pexpect.EOF])
if i == 0:
print 'Inside sshkey'
p.sendline('yes')
i = p.expect([ssh_key,'password:',pexpect.EOF])
if i == 1:
try:
p.sendline('mypassword') # this mypassword is shown in clear text on the console
p.interact()
p.logfile = sys.stdout
p.expect(pexpect.EOF)
except Exception,e:
print str(e)
gracefulExit()
if i == 2:
print 'Inside EOF block'
if p.isalive():
print '******************************************************'
print ' Closing the process of Download !!! '
print '******************************************************\n\n'
p.close()
Any inputs is highly appreciated..
Thanks.
-Vijay
There are few errors in the program:
p.interact()
This is used when we want to get back the control after having automatically supplied the password using pexpect module. You don't need to use that since you are automating the whole repository check out.
Also a few things can be improved, after passing the password, set a infinite timeout since it may take a while to copy a git repository.
p.expect(pexpect.EOF, timeout=None)
After that you can read all the execution output with the following command
output_lines = p.before
output_lines_list = output_lines.split('\r\n')
for line in output_lines: print line
you can also use the above to log the output to a file by directly writing to it
Using p.logifile = sys.stdout is not good since it will record pexpect operation from start including passing of password.
After this there is no need to close, you are not running a interactive program. Remove all these lines:
if i == 2:
print 'Inside EOF block'
if p.isalive():
print '******************************************************'
print ' Closing the process of Download !!! '
print '******************************************************\n\n'
p.close()
The issue is that some where you have to store the password and use it with p.sendline. How ever, you store password, it is going to be insecure. You can also take the input at the start for the password, this way you will not be storing the password within your program but that defeats automation. I don't see a way out but for taking password input, you can do:
import getpass
getpass.getpass("please provide your password")
To get rid of the password being echo'd to stdout, use the following when redirecting output -
p.logfile_read = sys.stdout # logs out the command
I have tried this myself and seems to be working. Here is the reference for this revelation.

Categories