Executing bash commands in python error [duplicate] - python

This question already has answers here:
How do I pipe a subprocess call to a text file?
(2 answers)
Closed 7 years ago.
I am trying to write a python script to test a 4 digit pincode with brute forcing(and a password) when connecting to local host. The command that needs to be run is:
echo password pincode | nc localhost 30002 >> /tmp/joesPin/pinNumber
(writes response to a new file).
This worked when written as a bash script, but I am struggling with the subprocess module in Python.
import subprocess
password = "UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ"
for i in range(10000):
pincode = str('{0:04}'.format(i)) #changes 4 to 0004
subprocess.call('echo', password, pincode,'|','nc localhost 30002 >> /tmp/joesPin/' + pincode,shell=True)
I want it to call:
echo UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 0001 | nc localhost 30002 >> /tmp/joesPin/0001

There are different ways to pipe the output of a command in Python.
Option 1: You can set the stdout argument of the subprocess.call command and write the output somewhere.
Option 2: You can use subprocess.PIPE in the Popencall and save the output to use with another command.
proc = subprocess.Popen(['echo', password, pincode], stdout=subprocess.PIPE)
output = proc.communicate()[0] # now contains the output of running "proc"
file = '/tmp/joesPin/pinNumber'
with open(file, 'a+') as out:
subprocess.call(['nc localhost 30002'], stdout=out, shell=True)
Setting the stdout field in subprocess.call writes the output of the subprocess to the file descriptor given in stdout.
To use the output of the 1st process as the stdin input of the 2nd process:
proc = subprocess.Popen(['echo', password, pincode], stdout=subprocess.PIPE)
output = proc.communicate()[0] # now contains the output of running "proc"
file = '/tmp/joesPin/pinNumber'
proc2 = subprocess.Popen(['nc localhost 30002'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
proc2.stdin.write(output)
result = proc2.communicate()[0]
# now you can write the output to the file:
with open (file, 'a+') as outfile:
outfile.write(result)

Related

Responding to an input when executing a python script through SSH

I am currently using a windows machine and trying to SSH to an Ubuntu Server, using PKI. I need to run the python script test.py using the sudo command. The script contains an input that will ask me for a number after running test.py. I have tried putting for a number after the sudo command but it did not work.
import subprocess
command = "ssh -t john#x.x.x.x echo 'john' | sudo -S python3.7 ./Desktop/test.py"
command = command.split()
out = subprocess.check_output(["scp", "test.py", "john#x.x.x.x:./Desktop"])
run_script = subprocess.run(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
Example of test.py:
import subprocess
choice = input("Choose a number: ")
if choice == 1:
result = subprocess.run(['cat' '/etc/passwd'], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
print(result.stdout.decode('utf-8'))
How can I respond to this input and where should I put it in my code?
If your remote command's standard input is connected to your Python script, simply use that.
run_script = subprocess.run(command,
stdout = subprocess.PIPE, stderr = subprocess.PIPE,
input="1\n", text=True)
I'm guessing you'll want to capture the output with capture=True, and probably also add check=True to the keyword arguments as well.
The addition of text=True saves you from having to encnde your input into bytes, and similarly from having to decode the output.

Log output of background process to a file

I have time consuming SNMP walk task to perform which I am running as a background process using Popen command. How can I capture the output of this background task in a log file. In the below code, I am trying to do snampwalk on each IP in ip_list and logging all the results to abc.txt. However, I see the generated file abc.txt is empty.
Here is my sample code below -
import subprocess
import sys
f = open('abc.txt', 'a+')
ip_list = ["192.163.1.104", "192.163.1.103", "192.163.1.101"]
for ip in ip_list:
cmd = "snmpwalk.exe -t 1 -v2c -c public "
cmd = cmd + ip
print(cmd)
p = subprocess.Popen(cmd, shell=True, stdout=f)
p.wait()
f.close()
print("File output - " + open('abc.txt', 'r').read())
the sample output from the command can be something like this for each IP -
sysDescr.0 = STRING: Software: Whistler Version 5.1 Service Pack 2 (Build 2600)
sysObjectID.0 = OID: win32
sysUpTimeInstance = Timeticks: (15535) 0:02:35.35
sysContact.0 = STRING: unknown
sysName.0 = STRING: UDLDEV
sysLocation.0 = STRING: unknown
sysServices.0 = INTEGER: 72
sysORID.4 = OID: snmpMPDCompliance
I have already tried Popen. But it does not logs output to a file if it is a time consuming background process. However, it works when I try to run background process like ls/dir. Any help is appreciated.
The main issue here is the expectation of what Popen does and how it works I assume.
p.wait() here will wait for the process to finish before continuing, that is why ls for instance works but more time consuming tasks doesn't. And there's nothing flushing the output automatically until you call p.stdout.flush().
The way you've set it up is more meant to work for:
Execute command
Wait for exit
Catch output
And then work with it. For your usecase, you'd better off using an alternative library or use the stdout=subprocess.PIPE and catch it yourself. Which would mean something along the lines of:
import subprocess
import sys
ip_list = ["192.163.1.104", "192.163.1.103", "192.163.1.101"]
with open('abc.txt', 'a+') as output:
for ip in ip_list:
print(cmd := f"snmpwalk.exe -t 1 -v2c -c public {ip}")
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) # Be wary of shell=True
while process.poll() is None:
for c in iter(lambda: process.stdout.read(1), ''):
if c != '':
output.write(c)
with open('abc.txt', 'r') as log:
print("File output: " + log.read())
The key things to take away here is process.poll() which checks if the process has finished, if not, we'll try to catch the output with process.stdout.read(1) to read one byte at a time. If you know there's new lines coming, you can switch those three lines to output.write(process.stdout.readline()) and you're all set.

Get all output from subprocess in python [duplicate]

This question already has answers here:
Running shell command and capturing the output
(21 answers)
Closed 4 years ago.
I'm using python 3.7 on Windows. I'm trying to execute a simple scan command and get its output as a string.
When I execute the command in python I only get the first line:
import subprocess
def execute(command):
proc = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
output = proc.stdout if proc.stdout else proc.stderr
path = "Somepath"
command = ['ecls.exe', '/files', path]
print(execute(command))
output:
WARNING! The scanner was run in the account of a limited user.
But when I run it in the CMD:
$ ecls.exe /files "SomePath"
WARNING! The scanner was run in the account of a limited user.
ECLS Command-line scanner ...
Command line: /files SomePath
Scan started at: 11/24/18 14:18:11
Scan completed at: 11/24/18 14:18:11 Scan time: 0 sec (0:00:00)
Total: files - 1, objects 1 Infected: files - 0, objects 0 Cleaned: files - 0, objects 0
I think that the command spawn a child process and it produces the scan output. I also tried to iterate over stdout but got the same output.
EDIT:
I tried other methods like check_output, Popen, etc with using PIPE but I only get the first line of output. I also tried to use shell=True but didn't make any difference. As I already said the command spawn a child process and I need to capture its output which seems that subprocess can't do it directly.
As I couldn't find a direct way to solve this problem, with help of this reference, the output can be redirected to a text file and then read it back.
import subprocess
import os
import tempfile
def execute_to_file(command):
"""
This function execute the command
and pass its output to a tempfile then read it back
It is usefull for process that deploy child process
"""
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.close()
path = temp_file.name
command = command + " > " + path
proc = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
if proc.stderr:
# if command failed return
os.unlink(path)
return
with open(path, 'r') as f:
data = f.read()
os.unlink(path)
return data
if __name__ == "__main__":
path = "Somepath"
command = 'ecls.exe /files ' + path
print(execute(command))

Python 2.6.6 - Need to add the output of OS.system command into another OS.system command [duplicate]

This question already has answers here:
Running shell command and capturing the output
(21 answers)
Closed 2 years ago.
Below is the script for searching a input data in a given OS.system command ( copied to file out.txt) and prints the line of the given input data. Now I want to put the output i.e line in another OS.system command. For example symaccess -sid 567 show -name xxx -type init where xxx is the output of the previous OS.system command i.e line.
Note - I can use only python 2.6.6 and the scripts related to storage
import os
os.system('symaccess -sid 456 list -type init > out.txt')
server = raw_input("server name:")
with open('out.txt', 'rt') as in_f:
for line in in_f:
if server in line:
print line
I used another method as below
import os server = raw_input("server name:")
var = "symaccess -sid 239 list -type init | grep \"{0}\"".format(server)
wwn = os.system(var)
init = 'symaccess -sid 239 -type init show {0}'.format(wwn) print init os.system(init)
above is the script i used to add a output of one os.system to another os.syste,. i got the first os.system executed but for the second one i.e os.system(init) is not coming because os.system(var) should be assigned as a variable.could someone tell how to assign a variable to os.system(init)
import subprocess
cmd= 'ls'
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
std_out = p.communicate()
Here is a possible way to access the output in Python.
Try using "subprocess.checkoutput()".
import subprocess
import os
output = subprocess.check_output(['symaccess -sid 456 list -type init'])
os.system(output)

Python redirect subprocess to file and to console [duplicate]

This question already has answers here:
Python subprocess get children's output to file and terminal?
(2 answers)
Closed 7 years ago.
Using Python, I want to create a subprocess and have its output redirected to both a file AND the console.
I found this post explaining how to print to both console and file, but solutions does not work when creating a subprocess:
sys.stdout = Logger()
print( "Hello") # printed to console and file
res = subprocess.call(cmd) # command output is printed to console only
Same behaviour here:
with Tee('outfile.log', 'w'):
print( "Hello" )
res = subprocess.call(cmd)
How can I redirect subprocess output both to console (for user) and to file (for me to check it from my code).
Note: Im' on Windows, so using system's tee is not appropriate.
Connect cmd's standard output to tee's stdin:
# cmd = ['/bin/echo', 'blah blah']
tee = subprocess.Popen(['/usr/bin/tee', 'outfile.log'], stdin=subprocess.PIPE)
subprocess.call(cmd, stdout=tee.stdin)
tee.stdin.close()
UPDATE For systems that does not have tee, read the output of the command and write it into stdout, and the log file:
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
universal_newlines=True)
with open('outfile.log', 'w') as f:
while True:
data = proc.stdout.read(1024)
if not data:
break
sys.stdout.write(data)
f.write(data)

Categories

Resources