python - Error when trying to receive output from check_output - python

My code is supposed to track down a packet sniffed with scapy and check which program sent/received the packet, put "Unknown" if the program isn't found
Code :
source_software = check_output(["netstat", "-nb"], shell = True).decode()
source_software = source_software[source_software.find(str(packet_dictionary["Port"])) : ]
source_software = source_software[source_software.find("\n") + 2 : source_software.find("]")]
if "Can not" not in source_software and len(source_software) > MINIMUM_LENGTH:
packet_dictionary["Software"] = source_software
else:
packet_dictionary["Software"] = "Unknown"
Errors :
File "Client.py", line 44, in add_to_list
source_software = check_output(["netstat", "-nb"], shell = True).decode()
File "C:\Python36\lib\subprocess.py", line 336, in check_output
**kwargs).stdout
File "C:\Python36\lib\subprocess.py", line 418, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['netstat', '-nb']' returned non-zero
exit status 1.

it could be python doesn't have permission to run netstat or any else, but you can debug it with the following command
source_software = check_output("netstat -nb; exit 0", stderr=subprocess.STDOUT, shell=True).decode()
print source_software

As you can see in the bottom line of the exceptions, the problem is that:
Command '['netstat', '-nb']' returned non-zero exit status 1.
...which means that is it not about check_output itself, rather it is just reporting back that the command you attempted to run using it, failed and exited with code 1.
You may want to run the command in the shell and check if it work as expected.

Related

check_output doesn't works in python 3.6 while subprocess works fine

i am trying to get the output of a command in my python program by using "check_output" method. but i'm getting this error:
out = check_output(command5 , shell=True)
File "/usr/lib64/python3.6/subprocess.py", line 336, in check_output
**kwargs).stdout
File "/usr/lib64/python3.6/subprocess.py", line 418, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_rht-ccp --results-arf arf.xml /usr/share/xml/scap/ssg/content/ssg-centos7-ds.xml' returned non-zero exit status 2.
this is the part of my program that is related:
command4 = "oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_rht-ccp --results-arf arf.xml /usr/share/xml/scap/ssg/content/ssg-centos7-ds.xml"
out = check_output(command4 , shell=True)
I am sure that the command is alright because I get the results when I write:
subprocess.call(command5,shell=True)
I am using python 3.6, and work in centos 7.
any idea why the check_output can not get the result?
This is entirely normal, because the command you ran produced a non-zero exit code. It means that the command you ran is signalling that something may be wrong.
See the subprocess.check_output() documentation:
If the return code was non-zero it raises a CalledProcessError.
and
This is equivalent to:
run(..., check=True, stdout=PIPE).stdout
where the check=True flag tells run() to raise an exception when return_value is not 0:
If check is true, and the process exits with a non-zero exit code, a CalledProcessError exception will be raised.
The other function you used, subprocess.call(), does not set check=True:
Run the command described by args. Wait for command to complete, then return the returncode attribute.
This is equivalent to:
run(...).returncode
So either don't use check_output(), or catch the exception thrown, or fix the command you are running. That call() worked is no indication that the process actually produced a successful result.
For example, you could use subprocess.run() directly:
proc = subprocess.run(
command5, shell=True, text=True
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if proc.returncode:
print(f'Issue reported, exit code {proc.returncode}, stderr:')
print(proc.stderr)
else:
print(proc.stdout)

plumbum.commands.processes.ProcessExecutionError: for commands which return null

The shell command I want to run, which returns nothing:
echo helloWorld | grep 'dummy'
plumbum version:
Following line works:
out=(echo["helloWorld"] | grep["h"])().strip()
But following line does not, what might be the reason?
out=(echo["helloWorld"] | grep["dummy"])().strip()
print(out)
Error I am having:
Traceback (most recent call last):
File "dd.py", line 6, in <module>
out=(echo["helloWorld"] | grep["dummy"])().strip()
File "/home/user/venv/lib/python3.5/site-packages/plumbum/commands/base.py", line 103, in __call__
return self.run(args, **kwargs)[1]
File "/home/user/venv/lib/python3.5/site-packages/plumbum/commands/base.py", line 240, in run
return p.run()
File "/home/user/venv/lib/python3.5/site-packages/plumbum/commands/base.py", line 201, in runner
return run_proc(p, retcode, timeout)
File "/home/user/venv/lib/python3.5/site-packages/plumbum/commands/processes.py", line 232, in run_proc
return _check_process(proc, retcode, timeout, stdout, stderr)
File "/home/user/venv/lib/python3.5/site-packages/plumbum/commands/processes.py", line 23, in _check_process
proc.verify(retcode, timeout, stdout, stderr)
File "/home/user/venv/lib/python3.5/site-packages/plumbum/commands/base.py", line 412, in verify
dstproc_verify(retcode, timeout, stdout, stderr)
File "/home/user/venv/lib/python3.5/site-packages/plumbum/machines/base.py", line 26, in verify
stderr)
plumbum.commands.processes.ProcessExecutionError: Command line: ['/bin/grep', 'dummy']
Exit code: 1
[Q] How could I fix this error?
This happens because the exit status of grep is 1 if it does not find anything, as described in its manual
You can try it in command line if you wish:
echo helloWorld | grep h; echo $?
echo helloWorld | grep x; echo $?
Will result in
helloWorld
0
1
Ways to circumvent this are described in another nice answer, e.g.
echo helloWorld | grep x | cat
will yield 0 as status. But unfortunately plumbum does a local pipe mechanism so grep output goes to plumbum, and then plumbum pipes it to the next command - meaning the cat can't swallow the exit code 1, there will be an exception thrown before it.
So my two ideas are to either create a shell script to run a grep never returning error on search without results:
#!/bin/bash
grep "$#" || test $? = 1
and execute this instead of the grep (called c1grep in the original answer), or to add a try/except block around your pipe code and manually handle the exit code 1 (ProcessExecutionError).
The other answer is correct but less than optimal - The problem can be solved in plumbum, without the need for an external script that wraps grep, and without having to catch the exception.
The idea is to use plumbum's run method to to do two things:
Force plumbum to accept any exit code from the called program (by default, an exception is raised if the returned error code is not zero).
Capture a tuple containing the error code, the standard output, and the standard error of the called program, and not just the standard output as plumbum normally does.
Working example:
for s in ["hello","dummy"]:
exitcode,stdout,stderr = (echo["helloWorld"] | grep[s]).run (retcode=None)
if exitcode == 0:
print (stdout.strip())
if exitcode != 0:
print (f"string {s} not present")
print (stderr)
The previous code returns:
helloWorld
string dummy not present
Without raising any exception.

Kill a python script from another script - CalledProcessError

I want to kill a python script that runs on my system from another python script.
I followed this answer and tweaked the code a bit, but got an error:
Traceback (most recent call last): File "/home/pi/base.py", line 13, in <module>
check_call(["pkill", "-9", "-f", script])
File "/usr/lib/python2.7/subprocess.py", line 540, in check_call
raise CalledProcessError(retcode, cmd)
CalledProcessError: Command '['pkill', '-9', '-f', '/home/pi/MotionDetector.py']' returned non-zero exit status 1
Code:
from subprocess import check_call
import sys
import time
script = '/home/pi/MotionDetector.py'
check_call(["pkill", "-9", "-f", script])
This means the pkill call has failed. Two possible reasons that come to mind:
it did not actually match any process. pkill would in this case not generate any output and return 1. You can verify this by trying to run pgrep instead of pkill and see what did it return on stdout (should be one or more lines with a PID in case of a match) and/or whether it also returned a non-zero status.
it did match, but user under which the pkill has been executed cannot kill the process(s) matched. In that case pkill should generate output on stderr similar to: pkill: killing pid 3244 failed: Operation not permitted
From the pkill(1) man page:
EXIT STATUS
...
1 No processes matched or none of them could be signalled.
...
It turns out it was just a bug.
The solution was simple, I copied my script to a new file, deleted the old one and it worked, simple as that.

CalledProcessError exit status code 5

I have been working with a short python script that executes bash commands. The program worked fine for about a month. Recently, I tried running the script passing it this command:
my_launcher.py -c /path/to/config/file.json
(BTW, when the command is entered in terminal, I causes no error and runs fine) and I get the following message:
RuntimeError: Command '['bash', '-c', 'my_launcher.py -c /path/to/config/file.json']' returns non-zero exit status (code5)
After looking on Google, I found definitions for return codes 0, 1, and 2, but nothing for code 5. Wondering if any of you knows anything about it. What it means? How can it be resolved? etc.
This is the python code that causes the error:
try :
#check_output produces byte string
#raises exception if command returns a non-zero exit status (error occurs during processing of command)
string_of_text_rc = subprocess.check_output(['bash', '-c', bashCommand])
except subprocess.CalledProcessError as e:
raise RuntimeError("Command '{}' returns non-zero exit status (code{})".format(e.cmd, e.returncode))
When removing try/except, here is the taceback:
Traceback (most recent call last):
File "bash_cmd.py", line 27, in <module>
run_cmd('my_launcher.py -c /path/to/config/file.json')
File "bash_cmd.py", line 17, in run_cmd
string_of_text_rc = subprocess.check_output(['bash', '-c', bashCommand])
File "/usr/lib64/python2.7/subprocess.py", line 575, in check_output
raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['bash', '-c', 'my_launcher.py -c /path/to/config/file.json']' returned non-zero exit status 5
**EDIT: The correct output is contained into e.output. Which means that the command is ran and returns correct output. I really don't know why I get this error code.
For the record, here's how you should run your .py file:
result = subprocess.check_output([
sys.executable, 'my_launcher.py', '-c', path_to_json])
And here is how you run shell commands:
result = subprocess.check_output(bash_command, shell=True)
For your problem - can you remove the try/except from your code, so we can see the full error traceback? Some good information might be hidden in there.

subprocess python - non zero exception

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

Categories

Resources