python shell command pipes grep no results
python shell command pipes grep no results
I am trying to get a domain name from a cpanel user in python.
Here is my code:
import subprocess
user = "testuser"
getuserdata = 'cat /var/cpanel/users/' + user
getdnsline = 'grep "DNS="'
test = 'wc -l'
userdataprocess = subprocess.Popen(getuserdata.split(), stdout=subprocess.PIPE)
testprocess = subprocess.Popen(test.split(), stdin=userdataprocess.stdout, stdout=subprocess.PIPE)
test, error = testprocess.communicate()
print(test)
dnslineprocess = subprocess.Popen(getdnsline.split(), stdin=userdataprocess.stdout, stdout=subprocess.PIPE)
website, error = dnslineprocess.communicate()
print(website.decode('utf-8').splitlines())
my output is:
b'60n'
So this means, that the wc -l command gives back 60 lines. So passing the output of the first getuserdata command to the wc -l command works.
However, the grep command always return blank. No matter it I put in "DNS=" or "=" or even "a". The file is the normal cpanel user file, and I have verified that DNS is in the file.
When I just output the data from the first process userdataprocess I can manually check for the DNS entry.
Do I have to do anything different when using the grep command in this fashion?
userdataprocess.stdout
dnslineprocess
testprocess
subprocess
2 Answers
2
Your script fails because of the quotes around DNS=
.
DNS=
You can use shell=True
to make the script work:
shell=True
dnslineprocess = subprocess.Popen(getdnsline, stdin=userdataprocess.stdout, stdout=subprocess.PIPE, shell=True)
Source: Passing double quote shell commands in python to subprocess.Popen()?
This is because your testprocess.communicate()
for the wc -l
command already consumes all of the output of userdataprocess.stdout
and closes it in fact, so there's nothing left for dnslineprocess.communicate()
to read.
testprocess.communicate()
wc -l
userdataprocess.stdout
dnslineprocess.communicate()
You should instead read the output of userdataprocess.stdout
into a variable and then use it as an input to both testprocess.communicate()
and dnslineprocess.communicate()
.
userdataprocess.stdout
testprocess.communicate()
dnslineprocess.communicate()
Also, as @pyb pointed out, you are unnecessarily quoting DNS=
in your grep
command, which, without a shell, will be passed to grep
with double quotes included as part of the string to filter with. You should simply remove them as there are no special characters in your filter string.
DNS=
grep
grep
import subprocess
user = "testuser"
getuserdata = 'cat /var/cpanel/users/' + user
getdnsline = 'grep DNS='
test = 'wc -l'
userdataprocess = subprocess.Popen(getuserdata.split(), stdout=subprocess.PIPE)
userdata = userdataprocess.stdout.read()
testprocess = subprocess.Popen(test.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
test, error = testprocess.communicate(userdata)
print(test)
dnslineprocess = subprocess.Popen(getdnsline.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
website, error = dnslineprocess.communicate(userdata)
print(website.decode('utf-8').splitlines())
That doesn't work. I thought of it too and commented the parts that call
wc -l
and got the same results.– pyb
Jul 1 at 17:44
wc -l
It actually does work, but the secondary problem is as pyb pointed out, that the OP unnecessarily quoted
DNS=
. I've edited the answer accordingly.– blhsing
Jul 1 at 17:50
DNS=
I stand corrected. There were 2 issues.
– pyb
Jul 1 at 19:00
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
userdataprocess.stdout
is empty whendnslineprocess
runs, becausetestprocess
consumed all of it already. I'm not aware of a simple workaround for that - but your use ofsubprocess
is entirely unnecessary anyway: everything you're doing with it (reading a file, counting lines, checking for specific text in those lines) is trivially doable in Python directly.– jasonharper
Jul 1 at 17:32