Can't seem to get pexpect to print data from command - python

I'm steadily working on how to ssh and parse data on a device by running a command. I have had a few questions along the way of this endeavor and much help with the questions I have asked. I'm now working with pexpect and I'm not seeing much in documentation with what I am doing. Basically I need to ssh in, as I said, and then run a command that will print out data, then get that data to print to my console.
Here is my code:
import pexpect
import pxssh
import getpass
child = pexpect.spawn('ssh www.example.com')
password = getpass.getpass('password: ')
child.sendline ('foo bar')
data = (child.read_nonblocking(size=1000, timeout=100))
print data
OUTPUT:
password:
foo bar
In the foo bar command the first line of the print out is foo bar so I am wondering if this is trying to print this data but only printing the first line. I add the read_nonblocking(size=1000, timeout=100) trying to set the size to be greater and a timeout to let the data print.
UPDATE with PXSSH
I have also tried to use the pxssh samples to do this and get only the list of commands that foo can run. I need to get the print out of foo bar which is the list of configs. My guess is that you can't have commands with spaces? Here is the code I have tried:
import pxssh
import getpass
try:
s = pxssh.pxssh()
s.force_password = True
hostname = raw_input('hostname: ')
username = raw_input('username: ')
password = getpass.getpass('password: ')
s.login (hostname, username, password)
s.sendline ('foo bar') # run a command
s.prompt() # match the prompt
print s.before # print everything before the prompt.
s.logout()
except pxssh.ExceptionPxssh, e:
print "pxssh failed on login."
print str(e)
Which gives me this back in console:
pxssh failed on login.
could not set shell prompt
:
Session idle time out is disabled
SSH> unset PROMPT_COMMAND
Error - Command [unset PROMPT_COMMAND] not found.
foo [ bar | bart | ran | up
| cmd | bee | hvac | monkey
| selective | list | help ]
check[v,nv,beep] [ list | help ]
delete [ all | bee | neewb | stuff
| up | cmd | fooconfig | root
| app | list | hvac | monkey
| selective | <filename> | confirmed | list | help ]
exit [ help ]
get [ vcf | nvcf | snmpcf | help ] [<filename>]
verbose [ help ]
help [ <command> | help ]
up arrow - brings up old command lines
down arrow - brings up newer command lines
right arrow - moves cursor to the right
left arrow - moves cursor to the left
insert - inserts a space at the cursor
delete - deletes character at the cursor
SSH> PS1='[PEXPECT]\$ '
Error - Command [PS1='[PEXPECT]\$ '] not found.
foo [ bar | bart | ran | up
| cmd | bee | hvac | monkey
| selective | list | help ]
check[v,nv,beep] [ list | help ]
delete [ all | bee | neewb | stuff
| up | cmd | fooconfig | root
| app | list | hvac | monkey
| selective | <filename> | confirmed | list | help ]
exit [ help ]
get [ vcf | nvcf | snmpcf | help ] [<filename>]
verbose [ help ]
help [ <command> | help ]
up arrow - brings up old command lines
down arrow - brings up newer command lines
right arrow - moves cursor to the right
left arrow - moves cursor to the left
insert - inserts a space at the cursor
delete - deletes character at the cursor
And as I mentioned I'm just trying to get the console to print out the foo bar command configs. This is the code I had working with python-exscript before finding out I needed to work in older Python 2.4.
CODE THAT I HAD WORKING IN EXSCRIPT THAT I NEED PEXPECT TO DO
account = read_login()
conn = SSH2()
conn.connect('example.com')
conn.login(account)
conn.execute('foo bar')
data = conn.response
conn.send('exit\r')
conn.close()
print data
Any help on how to get this code to work is greatly appreciated! Thanks!

Figured out the issue. I was missing a s.prompt()
try:
s = pxssh.pxssh(timeout=60, maxread=2000000)
s.force_password = True
hostname = raw_imput('hostname: ')
username = raw_input('password: ')
password = getpass.getpass('password: ')
s.PROMPT= 'SSH> '
s.login (hostname, username, password, auto_prompt_reset=False)
s.prompt()
s.sendline('foo bar')
s.prompt()
data = s.before
print data
s.logout()
except pxssh.ExceptionPxssh, e:
print "pxssh failed on login."
print str(e)

Related

Output format of subprocess python

I'm trying to keep the format generated by a command to see all wordpress plugin list.
my script is :
import subprocess
r = open("/tmp/resultplugin", "w")
f = open("path/to/my/list", "r")
for x in f:
x = x.rstrip()
bashCommand = "wp plugin list --allow-root"
process = subprocess.Popen(bashCommand, cwd=x, shell=True, stdout=r)
output, error = process.communicate()
The output of the command when launched directly on the bash shell :
| name | status | update | version |
+---------------------------------+----------+-----------+------------+
| plugin name | inactive | none | 5.2.2 |
| plugin name | active | none | 10.4.0 |
| plugin name | inactive | none | 5.65 |
| plugin | inactive | none | 9.4.8 |
The output when i redirect the output in a file :
name status update version
plugin name inactive none 5.2.2
plugin name active none 10.4.0
plugin name inactive none 5.65
plugin name inactive none 9.4.8
I have hard time to find how to keep the same format, or at least have a little bit more visibility as it's very hard to read in the file
Can someone explain me how i can format the output to the file correctly ?
Thank you

how to use jq tools or python as a output encoder to make result to translate to json formot is a difficult question

for a example
[root#test ~]# mysql -uroot -p'123123' -e"select user,host from mysql.user;"
+-------------------+-----------+
| user | host |
+-------------------+-----------+
| root | % |
| test | % |
| sqlaudit_test_mon | % |
| sysbase_test | % |
| mysql.session | localhost |
| mysql.sys | localhost |
+-------------------+-----------+
how to make search the result quick to convert to json format can you jq tools or python
such as that out put
[
{
"user":"root","host":"%"},
{
"user":"test","host":"%"},
{
"user":"sqlaudit_test_mon","host":"%"},
{
"user":"sysbase_test","host":"%"},
{
"user":"mysql.session","host":"localhost"},
{
"user":"mysql.sys","host":"localhost"}
]
i just want to know how to quick make search result to json,thank you!
it is better to user jq or python script it can make me search result to json format.
Just do it in your SELECT instead of pulling another program into a pipeline. MySQL has JSON functions. Ones of interest here are JSON_ARRAYAGG() and JSON_OBJECT(). Something like:
SELECT json_arrayagg(json_object('user', user, 'host', host)) FROM mysql.user;
should do it, plus whatever's needed to not print out that fancy table ascii art.
Here's an all-jq solution that assumes an invocation like this:
jq -Rcn -f program.jq sql.txt
Note in particular the -R ("raw input") and -n options.
def trim: sub(" *$";"") | sub("^ *";"");
# input: an array of values
def objectify($headers):
. as $in
| reduce range(0; $headers|length) as $i ({}; .[$headers[$i]] = ($in[$i]) ) ;
def preprocess:
select( startswith("|") )
| split("|")
| .[1:-1]
| map(trim) ;
reduce (inputs|preprocess) as $in (null;
if . == null then {header: $in}
else .header as $h
| .table += [$in|objectify($h)]
end )
| .table

multiple client server with python

I wrote a client and server program through the multi-threaded module, but I have a problem with the code
Consider the following output: (Clients are more than 2 (this is an example))
+---------+--------------+--------+
| [Index] | [IP-Address] | [Port] |
+---------+--------------+--------+
| 0 | 192.168.1.12 | 34224 |
| 1 | 192.168.1.10 | 39870 |
+---------+--------------+--------+
I want the server to send the corresponding command to the clients when the user enters the "chose [number]" command (like chose 0 1)
If user sending wrong number, like:
chose 2 3
chose 0 2
chose 2 0
chose
chose 0 (just one number)
Server show invalid selection
My output:
+---------+--------------+--------+
| [Index] | [IP-Address] | [Port] |
+---------+--------------+--------+
| 0 | 192.168.1.12 | 34232 |
| 1 | 192.168.1.10 | 40032 |
+---------+--------------+--------+
[BAT]> chose
[ERROR] Chose more than one!
[BAT]> chose 2 3
[WARNING] Not valid selection
[WARNING] Not valid selection
[BAT]> chose
[ERROR] Chose more than one!
[BAT]> chose 0
[ERROR] Chose more than one!
[BAT]> chose 0 1
[Multicasting-CMD]> mkdir test2
[STATUS] Success
[Multicasting-CMD]>
[WARNING] Command is empty!
[BAT]>
[WARNING] Command is empty!
And my code:
if "chose" in COMMAND:
Multicasting_check()
def Multicasting_check(COMMAND):
Target_list = COMMAND.replace("chose ", "")
Target_list = Target_list.split()
checking_list = []
if len(Target_list) > 1:
for conn_item in ALL_CONNECTIONS:
checking_list.append(ALL_CONNECTIONS.index(conn_item))
for Items in Target_list:
Int_items = int(Items)
if Int_items in checking_list:
Multicasting(Int_items)
else:
print "[WARNING] Not valid selection"
continue
else:
print "[ERROR] Chose more than one!"
def Multicasting(Conn_number):
Message = raw_input("[Multicasting-CMD]> ")
if len(Message) > 0:
if Message == "quit":
BAT()
try:
ALL_CONNECTIONS[Conn_number].send(str.encode(Message))
print colored("[STATUS]", "blue"), colored("Success", "green")
except socket.error:
print "[ERROR] Connection was lost with", ALL_HOST_ADDRESSES[Conn_number][0]
else:
print "[WARNING] Command is empty!"
All clients can't execute the commands
How can i fix it?
Thanks guys

How to update status on pretty table in python?

I am using python pretty table to print the status of each record on CLI.
How to display the status updates on the CLI in the same table.
Example:
+--------------+---------+
| Jobs | Status |
+--------------+---------+
| job1 | FAILED |
| job2 | SUCCESS |
+--------------+---------+
The jobs status will be updated by a thread. I want to display the updated status in the same table in CLI console.
I found ascii code to move the cursor to the previous line. And I am using the below logic to achieve the purpose
number_of_records = len(records) # number of jobs in a tables
total_lines = number_of_records + 3 + 1 # number of records + Borders + Header
if prev_lines != 0:
for i in range(prev_lines):
sys.stdout.write('\033[F')
prev_lines = total_lines
print status_table
Thanks :)

Python's Subprocess removing Mysql columns and spacing

Specifically, I am using:
Python 2.4.3 (#1, May 24 2008, 13:47:28)
[GCC 4.1.2 20070626 (Red Hat 4.1.2-14)] on linux2
I am trying to get the raw result of a mysql query with the column names and borders. Here is the raw command being run in bash:
[root#machine ~]# mysql -u root -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| dbA |
| dbB |
| dbC |
+--------------------+
I am having trouble storing this value into a variable in Python:
import subprocess
cmd_array = ["mysql", "-u", "root", "-e", "show databases"]
p = subprocess.Popen(cmd_array)
raw_data = p.communicate()[0]
# Console outputs:
# +--------------------+
# | Database |
# +--------------------+
# | dbA |
# | dbB |
# | dbC |
# +--------------------+
#
# raw_data is None
p = subprocess.Popen(cmd_array, stdout=subprocess.PIPE)
rawData = p.communicate()[0]
print rawData
# Console outputs:
# Database
# dbA
# dbB
# dbC
#
# rawData is "Database\ndbA\ndbB\ndbC"
What is the best way to store the pretty printed version of the mysql output in a python variable?
You need to use -t:
p = check_output(["mysql" ,"-u" ," root", "-t" ,"-e", 'show databases;'])
print(p)
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| world |
+--------------------+
You can also use check_output to store the output.
mysql operates differently depending on whether it is being called from a console (pseudo-terminal, pty) or being called from another program. When called from another program, it is purposefully terse for easier parsing. One way to think about it is that
"Database\ndbA\ndbB\ndbC"
is the raw result and
+--------------------+
| Database |
+--------------------+
| dbA |
| dbB |
| dbC |
+--------------------+
is a pretty-printed result for people.
I have no idea what a "column visible string" is, but if you want to process the data in your program, you got the easily parsed result you want.
If you really do want the fancy print version, you can use the pexpect or pty modules to emulate a terminal. Here's an example:
>>> import pexpect
>>> import subprocess
>>> child = pexpect.spawn('mysql -e "show databases"')
>>> child.expect(pexpect.EOF)
0
>>> print child.before
+--------------------+
| Database |
+--------------------+
| information_schema |
| test |
+--------------------+
Looks like mysql uses isatty() to determine if STDOUT is a terminal which then modifies the output.
I can get the table borders by specifying the --table or -t option:
cmd_array = ["mysql", "-t", "-u", "root", "-e", "show databases"]

Categories