Python - how to grep using a variable over ssh to remote machine - python

I'm trying to execute remote command over ssh.
all working well from the ssh connection and also with an other simple cmd command like 'ls'.
but, i would like to using ls and grep for a value stored in a variable(ptrn)
but i always failed.
i tried using:
cmd="ls -ltrd /export/home| grep %s ptrn"
cmd="ls -ltrd /export/home| grep" + ptrn
cmd="ls -ltrd /export/home| grep", ptrn
but no luck ):
my code:
BuildServer = 1.2.3.4
ptrn = "abc"
cmd="ls -ltrd /export/home| grep ptrn"
ssh = subprocess.Popen(["ssh", "%s" % BuildServer, cmd],shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print (ssh)
Can anyone please help me with that?
Thank you all.

If I read you correctly, you want to grep for the contents of the ptrn Python variable, so you need to pass that to grep, rather than its name, which doesn't mean anything in that context.
#!/usr/bin/env python
import subprocess
from pipes import quote
BuildServer = "1.2.3.4" # you pass it as a string to ssh
ptrn = "abc"
cmd="ls -ltrd /export/home| grep " + quote(ptrn) # Don't forget the space after grep.
ssh = subprocess.Popen(["ssh", "%s" % BuildServer, cmd], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print ssh.communicate()[0]
As for quote, this answer mentions it for quoting shell arguments, so that grep will consider it a single argument.
communicate() reads output from the process and waits for it to end.

You can try these:
cmd="ls -ltrd /export/home| grep %s"%ptrn
cmd="ls -ltrd /export/home| grep " + ptrn #notice the space

Related

How to convert output from Python after sudo command from <type> int to <type> str?

I have the following code to receive list of process with sudo:
sudoPass = 'mypass'
command = "launchctl list | grep -v com.apple"
x = os.system('echo %s|sudo -S %s' % (sudoPass, command))
But, I receive answer in int. I need in str. Is it possible to convert it to str without loosing data?
os.system returns (in most cases, see https://docs.python.org/3/library/os.html#os.system) the exit value of the process. Meaning most of the time 0 is everything went fine.
What you look for is the subprocess module (https://docs.python.org/3/library/subprocess.html) that allow you to capture output like so :
import subprocess
sudoPass = 'mypass\n' #Note the new line
command = "launchctl list | grep -v com.apple"
x = subprocess.Popen('echo %s|sudo -S %s' % (sudoPass, command), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
stdout, stderr = x.communicate()
print(stdout)

How to execute python subprocess.Popen with many Arguments?

I need to execute the same command on a local and remote server. So I'm using subprocess.Popen to execute, and local command work as expected, but when I execute on remote it gives me some error like command not found. I appreciate your support as I am new to this.
Local execution function
def topic_Offset_lz(self):
CMD = "/dsapps/admin/edp/scripts/edp-admin.sh kafka-topic offset %s -e %s | grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#' | awk -F\: '{print $3}'|sed '%sq;d'" % (self.topic,self.envr,self.partition)
t_out_lz, t_error_lz = subprocess.Popen(CMD, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
return t_out_lz
Remote server execution
def topic_offset_sl(self):
CMD = "/dsapps/admin/edp/scripts/edp-admin.sh kafka-topic offset %s -e %s | grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#' | awk -F\: '{print $3}'|sed '%sq;d'" % (self.topic, self.envr, self.partition)
t_out_sl, t_error_sl = subprocess.Popen(["ssh", "-q", CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
return t_error_sl
Error I'm getting for the remote execution
Landing Zone Offset: 0
SoftLayer Zone Offset: /bin/sh: ^# |sed 1: command not found
/bin/sh: d: command not found
I came up with below solution, might be there will easy way rather than this.
def topic_offset_sl(self):
CMD_SL1 = "ssh -q %s '/dsapps/admin/edp/scripts/edp-admin.sh kafka-topic offset %s -e %s'" % (KEY_SERVER,self.topic, self.envr)
CMD_SL2 = "| grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#' | awk -F\: '{print $3}'|sed '%sq;d'" % (self.partition)
t_out_sl, t_error_sl = subprocess.Popen(CMD_SL1 + CMD_SL2 , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
return t_out_sl
The ssh command passes its argument vector as a single command line string, not an array. To do this, it simply concatenates the arguments, without performing shell quoting:
$ ssh target "python -c 'import sys;print(sys.argv)'" 1 2 3
['-c', '1', '2', '3']
$ ssh target "python -c 'import sys;print(sys.argv)'" "1 2 3"
['-c', '1', '2', '3']
If there was proper shell quoting, the distinction between 1 2 3 and "1 2 3" would have been preserved, and the first argument would not need double-quoting.
Anyway, in your case, the following might work:
def topic_offset_sl(self):
CMD = "ssh -q " + pipes.quote("/dsapps/admin/edp/scripts/edp-admin.sh"
+ " kafka-topic offset %s -e %s" % (self.topic, self.envr)) \
+ "grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#'"
+ " | awk -F\: '{print $3}'|sed '%sq;d'" % self.partition
t_out_sl, t_error_sl = subprocess.Popen(CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
return t_error_sl
This assumes you only want to run the /dsapps/admin/edp/scripts/edp-admin.sh script remotely and not the rest.
Note that the way you use string splicing to construct command lines likely introduces shell command injection vulnerabilities (both locally and on the remote server).

Python - Sending Variable to subprocess

I have a list of IP addresses that I need to run a curl command on Remotely.
I am using a for loop to iterate through the ips.
The command that I need to run remotely is
curl --silent http://<IP>:9200/_cat/master | awk '{print $2}'
The above output will return an IP address of a master node in my cluster.
My code states
status = subprocess.Popen(["ssh", "%s" % ip, "curl http://ip:9200/_cat/master | awk '{print $2}'"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
I am having trouble passing the ip variable as part of my command.
I have also tried doing this.
status = subprocess.Popen(["ssh", "%s" % ip, "curl http://",ip,":9200/_cat/master | awk '{print $2}'"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
But it does not seem to work. How can I get this to work?
The third parameter will likely work better as one string. Try:
status = subprocess.Popen(
["ssh", "%s" % ip,
"curl http://%s:9200/_cat/master | awk '{print $2}'" % ip
], ....
I think I recall trying things your way, passing in the list, but had a lot of issues.
Instead, I've settled on passing in a single execution string just about everywhere in my code.
popen = subprocess.Popen(
"ping -n 1 %s" % "192.168.1.10",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
The one case where I used the list is an extremely simple exe call
popen = Popen( [sys.executable, script_name], stdout=output_file, stderr=output_file )

Commands in bash don't work when translated to Python

I have this commands in bash:
ACTIVE_MGMT_1=ssh -n ${MGMT_IP_1} ". .bash_profile; xms sho proc TRAF.*" 2>/dev/null |egrep " A " |awk '/TRAF/{print $1}' |cut -d "." -f2;
I was trying to do it in Python like this:
active_mgmgt_1 = os.popen("""ssh -n MGMT_IP_1 ". .bash_profile; xms sho proc TRAF.*" 2>/dev/null |egrep " A " |awk '/TRAF/{print $1}' |cut -d "." -f2""") ACTIVE_MGMT_1 = active_mgmgt_1.read().replace('\n', '')
It doesn't work; any advice please?
Your popen call needs be set to communicate via a pipe.
Also stop trying to put everything on one line - python doesn't require it and places a lot of empasis on readable code.
I would strongly suggest doing the string processing in python rather than egrep, (use find or re in python), awk (find or egrep) and cut (string split).
It is also recommended to use subprocess.Popen rather than os.popen functions. There is a suggestion to use shlex.spilt to clear up this sort of issue.
untested code
import subprocess
import re
import os
MGMT_IP_1 = os.getenv('MGMT_IP_1')
sp = subprocess.Popen(
['ssh', '-n', MGMT_IP_1, '. .bash_profile; xms sho proc TRAF.*'],
stdout=PIPE, stderr=None)
(result, outtext) = sp.communicate()
# Proceed to process outtext from here using re, find and split
# to the equivalent of egrep " A " |awk '/TRAF/{print $1}' |cut -d "." -f2;

Python 2.6 - passing | char into os.system in for loop

I have a list of IP's that I want to run a whois (using the linux tool whois) against and only see the Country option.
Here is my script:
import os
import time
iplist = open('ips.txt').readlines()
for i in iplist:
time.sleep(2)
print "Country: IP {0}".format(i)
print os.system("whois -h whois.arin.net + {0} | grep Country ".format(i))
So I want to display what IP is being ran, then I just want to see the Country info using grep. I see this error when I run it and the grep is not ran:
sh: -c: line 1: syntax error near unexpected token `|'
sh: -c: line 1: ` | grep Country '
this code below works so it must be an issue with my for loop:
print os.system("whois -h whois.arin.net + {0} | grep Country ".format('8.8.8.8'))
What am I doing wrong? Thank you!!!!
You're not stripping trailing newlines from the lines you read from the file. As a result, you are passing to os.system a string like "whois -h whois.arin.net + a.b.c.d\n | grep Country". The shell parses the string as two commands and complains of "unexpected token |" at the beginning of the second one. This explains why there is no error when you use a hand-made string such as "8.8.8.8".
Add i = i.strip() after the sleep, and the problem will go away.
user4815162342 is correct about the issue you are having, but might I suggest you replace os.system with subprocess.Popen? Capturing the output from the system call is not intuitive.. should you want to result to go anywhere but your screen, you'll likely going to have issues
from subprocess import Popen, PIPE
server = 'whois.arin.net'
def find_country(ip):
proc = Popen(['whois', '-h', server, ip], stdout = PIPE, stderr = PIPE)
stdout, stderr = proc.communicate()
if stderr:
raise Exception("Error with `whois` subprocess: " + stderr)
for line in stdout.split('\n'):
if line.startswith('Country:'):
return line.split(':')[1].strip() # Good place for regex
for ip in [i.strip() for i in open('ips.txt').readlines()]:
print find_country(ip)
Python is awesome at string handling- there should be no reason to create a grep subprocess to pattern match the output of a separate subprocess.
Try sh:
import os
import time
import re
import sh
iplist = open('ips.txt').readlines()
for i in iplist:
time.sleep(2)
print "Country: IP {0}".format(i)
print sh.grep(sh.whois(i, h="whois.arin.net"), "Country")

Categories