Subprocess python module issue when taking input from file - python

I am creating a python script for running the linux command which is " snmpwalk -v2c -c aL1walsh0aL <> ifInError"
I need to execute the command for multiple hosts IP which is in hostname.txt file.
When i run the python script below i am getting the output for "snmpwalk -v2c -c aL1walsh0aL" and the error for hostname not defined.
So basically my complete command is not executing which gives me correct output.
But i need the output for eg: snmpwalk -v2c -c aL1walsh0aL 10.0.0.1 ifInError
My python script:
import subprocess
with open("hostname.txt","rw") as f:
for line in f.readlines():
subprocess.Popen(['snmpwalk', '-v2c','-c',line],stdout=subprocess.PIPE)
f.close()

import subprocess
with open("mac.txt","rw") as f: # mac.txt is the text file with mac address
for line in f.readlines():
print (line)
print ("************")
process=subprocess.Popen(['macsearch', line],stdout=subprocess.PIPE)
out=process.communicate() """ using process.communicate to save the
output."""
for o in out:
print o
print ('\n')

Related

How to capture bash command output using python script

How to capture bash command output using python script.
For eg:
running below in linux :
[root#xxxxxx oracle]# echo sumit
sumit
[root#xxxxxx oracle]#
How can i re print only the above output using python script ? like running python test.py shoud give 'sumit' as output. i tried below:
test.py :
import sys
sys.stdout.flush()
out = sys.stdin.readline()
print(out)
Above prints only the input i type but not the already displayed output
With subprocess, you can run commands and check their return code, stdout and stderr outputs. Would that help?
For example:
import subprocess as proc
byte_output = proc.check_output(["ls", "-1", "."])
str_output = str(byte_output, "utf-8")
print(str_output)
# prints my local folders dev\ngit

Run a command with subprocess that has arguments as with & in Windows

I am trying to run through subprocess a command line command that receives as arguments files. However, these files might have characters like "&" and those can be interpreted as CMD commands if they are not between quotes (").
It usually worked and I had the command passed broken in a list.
Example:
from subprocess import run
file = r'broken&difficult.txt'
command = ['convert', file]
run(command)
However it will return an stdErr:
StdErr: 'diffcult.txt' is not recognized as an internal or external command, operable program or batch file
The returncode is 1.
I have tried to change the file name variable to:
file =r'"broken&difficult.txt"'
The result is that it is not able to find any file. With a returncode of 0
You need to use the CMD escape character - the carrot ^ - before the ampersand.
Try:
import subprocess
file = 'broken^&difficult.txt'
command = ['convert', file]
subprocess.run(command, shell=True)
Example of how this works:
import subprocess
# create a file
with open('broken&difficult.txt', 'w') as fp:
fp.write('hello\nworld')
# use `more` to have OS read contents
subprocess.run(['more', 'broken^&difficult.txt'], shell=True)
# prints:
hello
world
# returns:
CompletedProcess(args=['more', 'broken^&difficult.txt'], returncode=0)

excecute a python script with argument in another python script

I have a python script that should be called with two argument:
$ python ./script.py arg1 arg2
The content of this script is sth like this:
#!/usr/bin/python
import sys
import commands
if len(sys.argv) != 3:
print 'Usage: python %s <IP1> <IP2>' % (sys.argv[0])
sys.exit()
.
.
.
with open('/tmp/file.txt', 'r+') as f:
for line in f:
execfile("script.py --host $line")
But this is not correct, when I use this type of execfile this is wrong because:
it says the syntax is not correct..The correct form is execfile("script.py") but I have one argument and also I have variable line from my for loop
I want to run script.py with --host and variable that should be for each line from file.txt
How can I do that?
Thank you
execfile run a python script by loading it, not as a script. You should use os.system or subprocess.Popen for that.
for instance:
#!/usr/bin/python
import sys
import commands
import os # Change here!!
if len(sys.argv) != 3:
print 'Usage: python %s <IP1> <IP2>' % (sys.argv[0])
sys.exit()
.
.
.
with open('/tmp/file.txt', 'r+') as f:
for line in f:
os.system("script.py --host %s" % line)
run the command with subprocess will allows you store the standar and error ouput from the command.
Using subprocess:
import subprocess
with open('/tmp/file.txt', 'r+') as f:
for line in f:
proc = subprocess.Popen(["script.py", "--host", line], sdtout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate() # out: stadar output, err: error output

pexpect "no such file or directory" for a bash command that works

sCMD = 'ssh user#host cat some/path | grep "Oct 31\|Oct 30"'
child = pexpect.spawn(sCMD)
try:
child.expect("assword")
except pexpect.EOF:
raise Exception("Cannot connect to host")
child.sendline(ssh_pass)
lData = [s.strip(' \n\r:') for s in child.readlines()]
lData[0] reads "No such file or directory"
if I change the first line to read:
sCMD = 'ssh user#host cat some/path'
Then lData contains all the lines from the file.
But if I execute the exact same command (with the grep) in a terminal it works fine - it returns the text I expect. No complaints.
Any idea why the command performs differently when executed via pexpect?
sCMD = 'ssh user#host \'cat some/path | grep "Oct 31\|Oct 30"\''
for some reason pexpect requires those extra single quotes.

Using Python to cat a file over ssh to a remote bash script

I'm using subprocess.popen with shlex to call a remote bash script using ssh. This command works quite fine on bash itself. But as soon as I try to translate it to python and shlex with subprocess.popen it errs out.
Remote bash script:
#!/bin/bash
tmp="";
while read -r line;
do
tmp="$tmp $line\n";
done;
echo $tmp;
BASH CMD RESULT(Invoking the remote bash script on the command line)
$> ssh x.x.x.x cat < /tmp/bef69a1d-e580-5780-8963-6a9b950e529f.txt " | /path/to/bash/script.sh;"
Bar\n
$>
Python code
import shlex
import subprocess
fn = '/tmp/bef69a1d-e580-5780-8963-6a9b950e529f.txt'
s = """
ssh x.x.x.x cat < {localfile} '| /path/to/bash/script.sh;'
""".format(localfile=fn)
print s
lexer = shlex.shlex(s)
lexer.quotes = "'"
lexer.whitespace_split = True
sbash = list(lexer)
print sbash
# print buildCmd
proc=subprocess.Popen(sbash,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
out,err=proc.communicate()
print "Out: " + out
print "Err: " + err
PYTHON SCRIPT RESULT:
$> python rt.py
ssh x.x.x.x cat < /tmp/bef69a1d-e580-5780-8963-6a9b950e529f.txt '| /path/to/bash/script.sh'
['ssh', 'x.x.x.x', 'cat', '<', '/tmp/bef69a1d-e580-5780-8963-6a9b950e529f.txt', "'| /path/to/bash/script.sh'"]
Out:
Err: bash: /tmp/bef69a1d-e580-5780-8963-6a9b950e529f.txt: No such file or directory
$>
What am I missing?
The problem is that you're using shell redirection in the command, but there's no shell spawned when using subprocess.
Consider the following (very simple) program:
import sys
print sys.argv
Now if we run it like you're running ssh (assuming foofile.txt exists), we get:
python argcheck.py ssh cat < foofile.txt " | /path/to/bash/script.sh;"
['argcheck.py', 'ssh', 'cat', ' | /path/to/bash/script.sh;']
Notice that < foofile.txt never make it to python's commandline arguments. That's because the bash parser intercepts the < and the file that comes after it and redirects the contents of that file to your program's stdin. In other words, ssh is reading the file from stdin. You want your file to be passed to stdin of ssh using python as well.
s = """
ssh x.x.x.x cat '| /path/to/bash/script.sh;'
"""
#<snip>
proc=subprocess.Popen(sbash,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
out,err=proc.communicate(open(fn).read())
will work presumably.
The following works for me:
import subprocess
from subprocess import PIPE
with open('foo.h') as f:
p = subprocess.Popen(['ssh','mgilson#XXXXX','cat','| cat'],stdin=f,stdout=PIPE,stderr=PIPE)
out,err = p.communicate()
print out
print '#'*80
print err
And the equivalent command in bash:
ssh mgilson#XXXXX cat < foo.h '| cat'
where foo.h is a file on my local machine.

Categories

Resources