Here is the code in question:
import subprocess
import re
import os
p = subprocess.Popen(["nc -zv 8.8.8.8 53"], stdout=subprocess.PIPE, shell = True)
out, err = p.communicate()
regex = re.search("succeeded", out)
if not regex:
print ("test")
What i want it to do is to print out test if the regex does not match the netcat command. Right now im only matching on "succeeded" but that's all i need because the netcat command prints out :
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
The code runs fine but it matches when it shouldn't ?
The output is coming out stderr not stdout:
stderr=subprocess.PIPE
You can simplify to using in and you don't need shell=True:
p = subprocess.Popen(["nc", "-zv", "8.8.8.8", "53"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if "succeeded" not in err:
print ("test")
You can also redirect stderr to STDOUT and use check_output presuming you are using python >= 2.7:
out = subprocess.check_output(["nc", "-zv", "8.8.8.8", "53"],stderr=subprocess.STDOUT)
if "succeeded" not in out:
print ("test")
Related
I want to check the DNS value from my system.
If the command goes wrong, the error should be stored in a different variable.
This is what I have so far:
proc = subprocess.Popen(['echo', '"to stdout"'], stdout=subprocess.PIPE,)
stdout_value = proc.communicate()
print '\tstdout:', repr(stdout_value)
subprocess.call('echo #user', shell=True)
#subprocess.check_call('echo #HOME', shell=True)
You should try this :
It captures errorcode, stdout and stderr from a command you passed as an argument :
import shlex
from subprocess import Popen, PIPE
def get_exitcode_stdout_stderr(cmd):
"""
Execute the external command and get its exitcode, stdout and stderr.
"""
args = shlex.split(cmd)
proc = Popen(args, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
exitcode = proc.returncode
#
return exitcode, out, err
cmd = "..." # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)
For your need, I think you can use a python module to get what you want instead of using the bash cmd line. For example, to get your fully qualified domain name you can use :
socket.getfqdn()
I tried the below code to capture the output from screen using the sub-process, but its not doing what I intended to do.
#!/tools/bin/python
import subprocess
result = subprocess.check_output("echo $USERNAME", shell=True)
print result
expected output is:
vimo
vimo
i.e. one for the echo process and one for printing the result output.
But what I see is
vimo
But when I try to print the result output, its always empty.
What am I missing in the above puzzle !! Help out !!
Here you goes some greatly stripped (and altered for privacy reasons) raw dummy piece of code, grabbing both stdin and stdout from external script output.
from subprocess import Popen, PIPE
cmd = ['echo', 'foo']
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
comm = proc.communicate()
if proc.returncode != 0:
# code to handle / parse stderr (comm[1])
raise RuntimeError(
'\'%s\': command has failed (%d):\n%s'
% ('some value', proc.returncode, comm[1]))
for line in comm[0].split('\n'):
if line.find('Wrote:') == 0:
# some code to parse stdout
pass
Python >= 3.7 (tested with Python 3.9)
r=subprocess.run(['echo','$XDG_DATA_HOME'],capture_output=True,shell=True)
assert r.stdout.find(b'share')>0 # ERROR
r=subprocess.run('echo $XDG_DATA_HOME',capture_output=True,shell=True)
assert r.stdout.find(b'share')>0 # OK
Trying to write a script that checks a directory for files which then uses the names of the files found to insert in to a subprocess command as shown below:
for filename in os.listdir('/home/dross/python/scripts/var/running/'):
print(str(filename))
cmd = 'app_query --username=dross --password=/home/dross/dross.txt "select row where label = \'Id: ' + filename + '\' SHOW status"'
print(cmd)
query = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
query.wait()
If I run the command manually from the command line there are 2 possible values returned "Error:No result" or "True"
When the "Error: No result" condition is true the script returns the same however when the "True" condition is present nothing is returned.
If the result of the print statement is copied and pasted in to the os command line it runs and returns "True"
What could be the deception I am seeing here ?
Is there a better approach to achieve what I am trying to do ?
You seem to be missing a call to .communicate(), to read the results of the command through the pipe.
In your original query = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) then anything send to stderr will be displayed on the screen, which seems to be what's happening for your error message. Anything sent to stdout will be sent to the pipe, ready for reading with communicate()
Some experimenting, showing that you won't see what's written to the subprocess.PIPE channels unless you communicate with the command you've run, and that stderr will display to the terminal if it's not redirected:
>>> import subprocess
>>> query = subprocess.Popen('echo STDERR 1>&2', shell=True, stdout=subprocess.PIPE)
STDERR
>>> query.wait()
0
>>> print(query.communicate())
('', None)
>>> query = subprocess.Popen('echo STDERR 1>&2', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> query.wait()
0
>>> print(query.communicate())
('', 'STDERR\n')
>>> query = subprocess.Popen('echo STDOUT', shell=True, stdout=subprocess.PIPE)
>>> query.wait()
0
>>> print(query.communicate())
('STDOUT\n', None)
So, to use your code from the question, you want something like this:
for filename in os.listdir('/home/dross/python/scripts/var/running/'):
print(filename) # print can convert to a string, no need for str()
cmd = 'app_query --username=dross --password=/home/dross/dross.txt "select row where label = \'Id: ' + filename + '\' SHOW status"'
print(cmd)
query = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
query.wait()
output, error = query.communicate()
print("stdout: {}".format(output))
print("stderr: {}".format(error))
I try to get the output of a curl command by using the python subprocess. But the output is empty. Below is my source code:
def validateURL(url):
p = subprocess.Popen("curl",
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = False)
p.stdin.write("http://validator.w3.org/check?uri=" + url + "\n")
p.stdin.close()
stdout_data = p.stdout.read()
print stdout_data
result = re.findall("Error", stdout_data)
print result # empty here
if (len(result) != 0):
return 'ERR'
else:
return 'OK'
Why?
PS: I run this piece of code on my mac os and I use Python 2.7.
Drop the stderr = subprocess.PIPE,, and see the error message printed by curl. Act accordingly to fix it.
One possible reason is that the URL should be specified as a command-line argument, and not on stdin:
p = subprocess.Popen(("curl", "http://..."), stdout=subprocess.PIPE)
You were passing data to Popen after it executed the command.
Try this:
def validateURL(url):
p = subprocess.Popen(["curl", "http://validator.w3.org/check?uri=" + url + "\n"],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = False)
stdout_data = p.stdout.read()
print stdout_data
result = re.findall("Error", stdout_data)
print result # empty here
if (len(result) != 0):
return 'ERR'
else:
return 'OK'
You're not specifying the URL on the command line, so curl is printing an error message and exiting. Thus, there is no output on stdout. You're trying to send the URL on standard input, but curl does not work that way.
Instead, try:
p = subprocess.Popen(["curl", "http://validator.w3.org/check?uri=" + url],
stdout=subprocess.PIPE, shell=False)
Or, you know, just use urllib2 (or requests) and do it in native Python instead of shelling out to curl and dealing with all that plumbing.
This is a follow-up from Invoke pstools in Python script
When I open a command prompt and execute
D:\pstools\psloggedon.exe -l -x \\10.10.10.10
I get
DOMAIN\user
But when I execute the script
import sys, subprocess, socket, string
import wmi, win32api, win32con
pst = subprocess.Popen(
["D:\pstools\psloggedon.exe", "-l", "-x", "\\10.10.10.10"],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
out, error = pst.communicate()
print out, "is output"
I get
Error opening HKEY_USERS for \10.10.10.10
is output
How do I get the subprocess to read the IP address as \10.10.10.10 instead of \10.10.10.10
By the way, I tried to add third backslash
pst = subprocess.Popen(
["D:\pstools\psloggedon.exe", "-l", "-x", "\\\10.10.10.10"],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
And the output is
Error opening HKEY_USERS for .0.139.40
is output
As suggested by lejlot's comment you have to use "\\" because "\" is an escape character in python.