python call shell command and check response - python

Trying to write a function that reads the output of a shell command before making a decision.. For example:
6 def getCreds():
7 global access_key, secret_key, yourName
8 access_key = raw_input("Enter Access Key: ")
9 secret_key = raw_input("Enter Secret Key: ")
10 infoCorrect = raw_input('Is this information correct? (y or n)')
11 if infoCorrect.lower() == "yes" or infoCorrect.lower() =="y":
12 call (["./somecommand -u %s -p %s -flags" % (access_key, secret_key) + tfdir],shell=True)
13 else:
The output of the shell command is either
"You have successfully logged in"
or
"you cannot log in"
So I dont know the right syntax to go :
if response = "You have successfully logged in" :
(some action)
elif:
(some action)
How to I read the response?
Thanks!

use Popen() method defined in subprocess and redirect your output to PIPE. try this code:
import subprocess
p = subprocess.Popen("ls", shell=True, stdout = subprocess.PIPE)
output,err = p.communicate()
print(output)

I dont think output of shell command can be returned. You could only check that whether the command is successful or returned an error.
Having said that you could redirect your output to a file and then examine its content.
f = open("outputFile","wb")
call (["./somecommand -u %s -p %s -flags" % (access_key, secret_key) + tfdir],shell=True,stdout=f)
If you want to avoid writing to file then you may want to look at StringIO module.

Related

How to parse a Linux terminal error message in 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)

how to make a variable case insensitive?

I want change the below code to run the command adb -s %s get-state"%(adb_id) such that the adb_id is made case-insensitive,it should work if the adb_id is 1281b6a1 or 1281B6A1 ?can anyone provide guidance on how to do that?
import subprocess
from subprocess import Popen, PIPE, STDOUT
#adb_id = '1281b6a1'
adb_id = '1281B6A1'
cmd = r"C:\adb -s %s get-state"%(adb_id)#cmd = os.getcwd() + "\\adb devices"
proc = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(output,error) = proc.communicate()
#Check if adb detects any devices
if error != '':
print "ERROR:%s"%error
else :
print "Provided Id is found in ADB as ", output
print str ( output ).strip()
You can't make adb case-insensitive, so if you want the user to be able to enter the device ID without worrying about case, you'll need to find the correct case of the device's name and pass that to adb.
And to do that you'll need to get the output of adb devices to find the device's actual name. Then find what the user entered in that device list using a case-insensitive search, and finally return the canonical device name from that.
devlist = subprocess.check_output("adb devices")
devname = "\r\n%s\t" % adb_id.lower() # device name is followed by tab
posn = devlist.lower().find(devname)
if posn + 1: # found
adb_id = devlist[posn+2:posn+2+len(adb_id)]
else:
print("that device is not connected")
Now adb_id is the case-corrected version of the device ID and can be passed via subprocess to adb.
A better solution is probably to use the output of adb devices to make a menu. That way the user doesn't have to type the full device name.

Enter an ssh password using the standard python library (not pexpect)

Related questions that are essentially asking the same thing, but have answers that don't work for me:
Make python enter password when running a csh script
How to interact with ssh using subprocess module
How to execute a process remotely using python
I want to ssh into a remote machine and run one command. For example:
ssh <user>#<ipv6-link-local-addr>%eth0 sudo service fooService status
The problem is that I'm trying to do this through a python script with only the standard libraries (no pexpect). I've been trying to get this to work using the subprocess module, but calling communicate always blocks when requesting a password, even though I supplied the password as an argument to communicate. For example:
proc = subprocess.Popen(
[
"ssh",
"{testUser1}#{testHost1}%eth0".format(**locals()),
"sudo service cassandra status"],
shell=False,
stdin=subprocess.PIPE)
a, b = proc.communicate(input=testPasswd1)
print "a:", a, "b:", b
print "return code: ", proc.returncode
I've tried a number of variants of the above, as well (e.g., removing "input=", adding/removing subprocess.PIPE assignments to stdout and sterr). However, the result is always the same prompt:
ubuntu#<ipv6-link-local-addr>%eth0's password:
Am I missing something? Or is there another way to achieve this using the python standard libraries?
This answer is just an adaptation of this answer by Torxed, which I recommend you go upvote. It simply adds the ability to capture the output of the command you execute on the remote server.
import pty
from os import waitpid, execv, read, write
class ssh():
def __init__(self, host, execute='echo "done" > /root/testing.txt',
askpass=False, user='root', password=b'SuperSecurePassword'):
self.exec_ = execute
self.host = host
self.user = user
self.password = password
self.askpass = askpass
self.run()
def run(self):
command = [
'/usr/bin/ssh',
self.user+'#'+self.host,
'-o', 'NumberOfPasswordPrompts=1',
self.exec_,
]
# PID = 0 for child, and the PID of the child for the parent
pid, child_fd = pty.fork()
if not pid: # Child process
# Replace child process with our SSH process
execv(command[0], command)
## if we havn't setup pub-key authentication
## we can loop for a password promt and "insert" the password.
while self.askpass:
try:
output = read(child_fd, 1024).strip()
except:
break
lower = output.lower()
# Write the password
if b'password:' in lower:
write(child_fd, self.password + b'\n')
break
elif b'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
write(child_fd, b'yes\n')
else:
print('Error:',output)
# See if there's more output to read after the password has been sent,
# And capture it in a list.
output = []
while True:
try:
output.append(read(child_fd, 1024).strip())
except:
break
waitpid(pid, 0)
return ''.join(output)
if __name__ == "__main__":
s = ssh("some ip", execute="ls -R /etc", askpass=True)
print s.run()
Output:
/etc:
adduser.conf
adjtime
aliases
alternatives
apm
apt
bash.bashrc
bash_completion.d
<and so on>

Pass a variable to a path/command in python

I am new to Python. I want to execute a script which has parameters in python. Please have a look at below example on what I finally want to achieve.
I have a script with parameters:
PATH="ABCXYZ"
username = "admin"
password = "pass"
query = "select * from user;"
OUTPUT = /usr/local/<PATH>/dbscript -u username -p password -q query
How can I pass a PATH variable in "/usr/local/<PATH>/dbscript" here ?
I tried with os.system & subprocess, But We cannot use variable in between.
I want that OUTPUT variable data which will print yes or no or some number
Below must work.
import subprocess as sp
PATH="ABCXYZ"
username = "admin"
password = "pass"
query = "select * from user;"
command = "/usr/local/%s/dbscript -u %s -p %s -q %s" % (PATH, username, password, query)
#Next line print '/usr/local/ABCXYZ/dbscript -u admin -p pass -q select * from user;' for me.
print command #
sp.Popen(command.split(), shell=True)
Furthermore you should play with shell parameter and useful read it.

How to create a user in linux using python

How do I create a user in Linux using Python? I mean, I know about the subprocess module and thought about calling 'adduser' and passing all the parameters at once, but the 'adduser' command asks some questions like password, full name, phone and stuff. How would I answer this questions using subprocess?
I've seen module called pexpect in this question: Can I use Python as a Bash replacement?. Is there any other standard module?
Use useradd, it doesn't ask any questions but accepts many command line options.
On Ubuntu, you could use the python-libuser package
import os
import crypt
password ="p#ssw0rd"
encPass = crypt.crypt(password,"22")
os.system("useradd -p "+encPass+" johnsmith")
You could just use the built-in binaries so just call useradd or something through the subprocess module, However I don't know if there's any other modules that hook into Linux to provide such functionality.
def createUser(name,username,password):
encPass = crypt.crypt(password,"22")
return os.system("useradd -p "+encPass+ " -s "+ "/bin/bash "+ "-d "+ "/home/" + username+ " -m "+ " -c \""+ name+"\" " + username)
This is a solution where shell is false.
#!/bin/env/python
import subprocess
import traceback
import sys
def user_add(username, user_dir=None):
if user_dir:
cmd = ["sudo", "useradd", "-d", user_dir, "-m", username]
else:
cmd = ["sudo", "useradd", username]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = p.communicate()
output = output.strip().decode("utf-8")
error = error.decode("utf-8")
if p.returncode != 0:
print(f"E: {error}")
raise
return output
try:
username = "user"
output = user_add(username)
print(F"Success. {username} is added")
except:
traceback.print_exc()
sys.exit(1)

Categories