I would like to run the subprocess.check_output method for my python script.
try:
logger.info('Loading URL ' + line)
wp_output = subprocess.checkout(['ruby', PATH + '/wpscan.rb', '--url', line, '--enumerate',
'vp', '--enumerate', 'vt'])
print wp_output
logger.info(wp_output)
return wp_output.strip()
except KeyboardInterrupt:
raise
except subprocess.CalledProcessError, e:
logger.exception('ERROR - Problem occurred while using wpscan.')
the exception:
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 573, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command '[u'ruby', u'./wpscan/wpscan.rb', u'--url', 'www.website.de', u'--enumerate', u'vp', u'--enumerate', u'vt']' returned non-zero exit status 1
if I run check_output I get a non-zero exception, if I use only "subprocess.call" I get as result "print wp_output" only the int 1??
What I am doing wrong? I would like to get the output as a string (wp_output).
When you run subprocess.call is returns an int that represents the exit code of the program. Typically a 0 means everything ran fine, and other numbers, such as your 1, indicate an error.
subprocess.check_output will specifically treat an error as an exception within python itself, and raise it, which leads to your result.
If you want the string output whether it was an error or a success, use Popen.
command = ['ruby', PATH + '/wpscan.rb', '--url', line, '--enumerate',
'vp', '--enumerate', 'vt']
wp_output = subprocess.Popen(command, stdout=subprocess.PIPE)
wp_output = wp_output.communicate()
print wp_output
Using Popen with subprocess.PIPE and then running communicate on it will gives you a tuple containing the text that your command returned, whether it's an error or not.
This is an addon to SuperBiasedMan's comment. It will be nice to redirect the stderr too as errors usually appear in stderr than stdout.
command = ['ruby', PATH + '/wpscan.rb', '--url', line, '--enumerate',
'vp', '--enumerate', 'vt']
wp_proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
wp_output, wp_error = wp_proc.communicate()
if wp_error != '':
print wp_error
else:
print wp_output
Related
I'm trying to run a process with subprocess and print its entire output if and only if an exception occurs.
Where I was before:
try:
proc = subprocess.run(
command,
capture_output=True,
check=True,
text=True,
)
except subprocess.CalledProcessError as error:
print(error.output)
This did not work.
Output when subprocess.CalledProcessError occurs:
b''
Replacing capture_output with stdout=subprocess.PIPE resulted in the output of everything regardless whether an exception occurred or not, error.output was still empty.
So I experimented:
This prints everything I would see if I executed the command in the command-line.
subprocess.run(
command,
stdout=subprocess.PIPE,
)
This prints out nothing.
proc = subprocess.run(
command,
capture_output=True,
)
print(proc.stdout.decode())
I also tried subprocess.check_output() which to my information does the same as subprocess.run() with the flags I set in the first code snippet.
What am I missing here? Thanks.
Addendum
import subprocess
command = ['pandoc', 'file']
try:
proc = subprocess.run(
command,
capture_output=True,
check=True,
)
except subprocess.CalledProcessError as error:
print('Exception:')
print(error.output)
This is an MWE with the specific process I want to run (pandoc)
Output
$ pandoc file
pandoc: file: openBinaryFile: does not exist (No such file or directory)
$ ./samplecode.py
Exception:
b''
So the exception gets triggered, but the output object is empty.
It seems that the error message is present in error.stderr and not in error.output. I tried your example (with a ls of non-existent file) :
import subprocess
command = ['ls', 'file']
try:
proc = subprocess.run(
command,
check=True,
capture_output=True,
text=True
)
except subprocess.CalledProcessError as error:
print('Exception:')
print('output : ' + error.output)
print('stderr : ' + error.stderr)
The output is the following :
Exception:
output :
stderr : ls: file: No such file or directory
Hope it helps.
I believe what you're meaning to run is stderr=subprocess.PIPE. This should print the relevant error code to the standard console error output.
Example:
process = subprocess.Popen(['ls', 'myfile.txt'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(output,error) = process.communicate()
if error:
print error
I have a NSIS script that accepts an argument ${appname} and creates an installer based on the given name, the nsis script is called from a python script, which also does other stuff. This is the code I am using for calling the NSIS script
def run_nsis_process(self,product_name,script, logger):
NSIS_PATH='C:/Program Files (x86)/NSIS'
try:
nsis_args = '/Dappname='+product_name+ ' '+ script
process_completed = subprocess.run(['makensis.exe', nsis_args], shell=True, cwd = NSIS_PATH, universal_newlines = True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True)
except subprocess.CalledProcessError as err:
logger.error('The makensis.exe subprocess existed with the following code {} \n The makensis.exe produced the following error text{}'.format(err.returncode, err.output))
else:
logger.info('Output from NSIS:\n{}'.format(process_completed.stdout))
This gives me an error that I am not using the correct makensis.exe arguments. Just for information the /Dappname=value accepts the value and sends it to the makensis script as an argument to the nsis script. The error I get is
The makensis.exe produced the following error textCommand line defined: "appname=EDMsdk O:\dev/product/NSIS/installer.nsi"
If I replace the subprocess.run with os.system as so
def run_nsis_process(self,product_name,script, logger):
NSIS_PATH='C:/Program Files (x86)/NSIS'
try:
nsis_args = '/Dappname='+product_name+ ' '+ script
nsis_cmd = 'makensis.exe /Dappname='+product_name+ ' '+ script
#process_completed = subprocess.run(['makensis.exe', nsis_args], shell=True, cwd = NSIS_PATH, universal_newlines = True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True)
os.system(nsis_cmd)
except subprocess.CalledProcessError as err:
logger.error('The makensis.exe subprocess existed with the following code {} \n The makensis.exe produced the following error text{}'.format(err.returncode, err.output))
else:
logger.info('Output from NSIS:\n{}'.format(process_completed.stdout))
than everything works and I get the installer executable.
I don't know what I'm doing wrong here, any suggestions
cheers,
es
Try this one
def run_nsis_process(self,product_name,script, logger):
NSIS_PATH='C:/Program Files (x86)/NSIS'
try:
nsis_args = ['/Dappname=', product_name, script]
process_completed = subprocess.run(['makensis.exe'] + nsis_args, shell=True, cwd = NSIS_PATH, universal_newlines = True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True)
except subprocess.CalledProcessError as err:
logger.error('The makensis.exe subprocess existed with the following code {} \n The makensis.exe produced the following error text{}'.format(err.returncode, err.output))
else:
logger.info('Output from NSIS:\n{}'.format(process_completed.stdout))
The problem is that you passed one argument
Here is my code:
from subprocess import check_output
print check_output('whoami', shell=True)
This works fine.
However, if I put a command that isnt' existent it will say:
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command 'test' returned non-zero exit status 1
When if you were to run this on your shell, it would say something like:
'test' isnot recognized as an intenral or external command, operable program or batch file.
How can I get this instead?
As you can read in the subprocess.check_output documentation:
If the return code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and any output in the output attribute.
So you can do this:
import subprocess
try:
print subprocess.check_output('test', shell=True)
except subprocess.CalledProcessError, e:
print e.output
I'm attempting to call an outside program from my python application, but it shows no output and fails with error 127. Executing the command from the command line works fine. (and I am in the correct working directory)
def buildContris (self, startUrl, reportArray):
urls = []
for row in reportArray:
try:
url = subprocess.check_output(["casperjs", "casper.js", startUrl, row[0]], shell=True)
print (url)
urls.append(url)
break
except subprocess.CalledProcessError as e:
print ("Error: " + str(e.returncode) + " Output:" + e.output.decode())
return urls
Each loop outputs the following error: (I've also checked e.cmd. It's correct, but long, so I omitted it in this example)
Error: 127 Output:
SOLUTION:
The following code works
app = subprocess.Popen(["./casperjs/bin/casperjs", "casper.js", startUrl, row[0]], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env = {"PATH" : "/usr/local/bin/:/usr/bin"}, universal_newlines=True)
app.wait()
out, errs = app.communicate()
Try adding the full path to casperjs in your subprocess.check_output() call.
Edit: Answeing your 2nd question. My apologies for the formatting as I'm on iPad.
I think you should try Popen instead of check_output so that you can specify environment variables:
p = subprocess.Popen(["/path/to/casperjs", "casper.js", startUrl, row[0]], env={"PATH": "/path/to/phantomjs"})
url, err = p.communicate()
shell=True changes the interpretation of the first argument (args) in check_output() call, from the docs:
On Unix with shell=True, ... If args is a
sequence, the first item specifies the command string, and any
additional items will be treated as additional arguments to the shell
itself. That is to say, Popen does the equivalent of:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
Exit status 127 might mean that the shell haven't found casperjs program or casperjs itself exited with that code.
To fix the code: drop shell=True and specify the full path to the casperjs program e.g.:
url = check_output(["./casperjs", "casper.js", startUrl, row[0]])
Try to add explicitly the path in this way.
If the file to call is in the same path (change __file__ if not):
cwd=os.path.dirname(os.path.realpath(__file__))
a = subprocess.check_output(["./casper.js", startUrl, row[0]],cwd=cwd,shell=True)
If you're experiencing this kinda nonsense on macOS: don't use aliases. Lost half a day with that. So, change:
subprocess.check_output(
"scribus-ng -g -ns -py {0} {1}".format(script_path, id),
stderr=subprocess.STDOUT,
shell=True)
to
subprocess.check_output(
"/Applications/Scribus.app/Contents/MacOS/Scribus -g -ns -py {0} {1}".format(script_path, id),
stderr=subprocess.STDOUT,
shell=True)
I am calling the executable from python script using sub process call. these are the following code I have used:
try:
p = subprocess.Popen([abc.exe], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
except Exception as e:
print str(e)
from abc.exe, I have return 1 in failure case and return 0 for success case. But I don't know how to check the return value in python script.
thanks,
Popen.returncode contains the return code when the process has terminated. You can ensure that using Popen.wait.
You've saved as p the output from .communicate(), not Popen object. Perhaps try:
try:
p = subprocess.Popen(['abc.exe'], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError as e:
print str(e)
stdoutdata, stderrdata = p.communicate()
retcode = p.returncode
Another way to do this is to use subprocess.check_output() since you mention Python 2.7. This runs the command with the same arguments as Popen. The output of the command is returned as a string. If the command returns a non-zero value, a subprocess.CalledProcessError exception is raised.
So I think you can rework your code to something like this:
try:
output = subprocess.check_output(['abc.exe'], shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as ex:
# an error occurred
retcode = ex.returncode
output = ex.output
else:
# no error occurred
process(output)
Note that you can't use the stdout argument in check_output since it is used internally. Here are the docs.